|  | @@ -6,6 +6,40 @@ namespace Renci.SshNet
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  |      internal class ClientAuthentication : IClientAuthentication
 |  |      internal class ClientAuthentication : IClientAuthentication
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  | 
 |  | +        private readonly int _partialSuccessLimit;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        /// <summary>
 | 
											
												
													
														|  | 
 |  | +        /// Initializes a new <see cref="ClientAuthentication"/> instance.
 | 
											
												
													
														|  | 
 |  | +        /// </summary>
 | 
											
												
													
														|  | 
 |  | +        /// <param name="partialSuccessLimit">The number of times an authentication attempt with any given <see cref="IAuthenticationMethod"/> can result in <see cref="AuthenticationResult.PartialSuccess"/> before it is disregarded.</param>
 | 
											
												
													
														|  | 
 |  | +        /// <exception cref="ArgumentOutOfRangeException"><paramref name="partialSuccessLimit"/> is less than one.</exception>
 | 
											
												
													
														|  | 
 |  | +        public ClientAuthentication(int partialSuccessLimit)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            if (partialSuccessLimit < 1)
 | 
											
												
													
														|  | 
 |  | +                throw new ArgumentOutOfRangeException("partialSuccessLimit", "Cannot be less than one.");
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            _partialSuccessLimit = partialSuccessLimit;
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        /// <summary>
 | 
											
												
													
														|  | 
 |  | +        /// Gets the number of times an authentication attempt with any given <see cref="IAuthenticationMethod"/> can
 | 
											
												
													
														|  | 
 |  | +        /// result in <see cref="AuthenticationResult.PartialSuccess"/> before it is disregarded.
 | 
											
												
													
														|  | 
 |  | +        /// </summary>
 | 
											
												
													
														|  | 
 |  | +        /// <value>
 | 
											
												
													
														|  | 
 |  | +        /// The number of times an authentication attempt with any given <see cref="IAuthenticationMethod"/> can result
 | 
											
												
													
														|  | 
 |  | +        /// in <see cref="AuthenticationResult.PartialSuccess"/> before it is disregarded.
 | 
											
												
													
														|  | 
 |  | +        /// </value>
 | 
											
												
													
														|  | 
 |  | +        internal int PartialSuccessLimit
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            get { return _partialSuccessLimit; }
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        /// <summary>
 | 
											
												
													
														|  | 
 |  | +        /// Attempts to authentication for a given <see cref="ISession"/> using the <see cref="IConnectionInfoInternal.AuthenticationMethods"/>
 | 
											
												
													
														|  | 
 |  | +        /// of the specified <see cref="IConnectionInfoInternal"/>.
 | 
											
												
													
														|  | 
 |  | +        /// </summary>
 | 
											
												
													
														|  | 
 |  | +        /// <param name="connectionInfo">A <see cref="IConnectionInfoInternal"/> to use for authenticating.</param>
 | 
											
												
													
														|  | 
 |  | +        /// <param name="session">The <see cref="ISession"/> for which to perform authentication.</param>
 | 
											
												
													
														|  |          public void Authenticate(IConnectionInfoInternal connectionInfo, ISession session)
 |  |          public void Authenticate(IConnectionInfoInternal connectionInfo, ISession session)
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
												
													
														|  |              if (connectionInfo == null)
 |  |              if (connectionInfo == null)
 | 
											
										
											
												
													
														|  | @@ -44,10 +78,10 @@ namespace Renci.SshNet
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -        private static bool TryAuthenticate(ISession session,
 |  | 
 | 
											
												
													
														|  | -                                            AuthenticationState authenticationState,
 |  | 
 | 
											
												
													
														|  | -                                            string[] allowedAuthenticationMethods,
 |  | 
 | 
											
												
													
														|  | -                                            ref SshAuthenticationException authenticationException)
 |  | 
 | 
											
												
													
														|  | 
 |  | +        private bool TryAuthenticate(ISession session,
 | 
											
												
													
														|  | 
 |  | +                                     AuthenticationState authenticationState,
 | 
											
												
													
														|  | 
 |  | +                                     string[] allowedAuthenticationMethods,
 | 
											
												
													
														|  | 
 |  | +                                     ref SshAuthenticationException authenticationException)
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
												
													
														|  |              if (allowedAuthenticationMethods.Length == 0)
 |  |              if (allowedAuthenticationMethods.Length == 0)
 | 
											
												
													
														|  |              {
 |  |              {
 | 
											
										
											
												
													
														|  | @@ -58,40 +92,39 @@ namespace Renci.SshNet
 | 
											
												
													
														|  |              // we want to try authentication methods in the order in which they were
 |  |              // we want to try authentication methods in the order in which they were
 | 
											
												
													
														|  |              // passed in the ctor, not the order in which the SSH server returns
 |  |              // passed in the ctor, not the order in which the SSH server returns
 | 
											
												
													
														|  |              // the allowed authentication methods
 |  |              // the allowed authentication methods
 | 
											
												
													
														|  | -            var matchingAuthenticationMethods = GetAllowedAuthenticationMethodsThatAreSupported(authenticationState, allowedAuthenticationMethods);
 |  | 
 | 
											
												
													
														|  | 
 |  | +            var matchingAuthenticationMethods = authenticationState.GetSupportedAuthenticationMethods(allowedAuthenticationMethods);
 | 
											
												
													
														|  |              if (matchingAuthenticationMethods.Count == 0)
 |  |              if (matchingAuthenticationMethods.Count == 0)
 | 
											
												
													
														|  |              {
 |  |              {
 | 
											
												
													
														|  | -                authenticationException = new SshAuthenticationException(string.Format("No suitable authentication method found to complete authentication ({0}).", string.Join(",", allowedAuthenticationMethods)));
 |  | 
 | 
											
												
													
														|  | 
 |  | +                authenticationException = new SshAuthenticationException(string.Format("No suitable authentication method found to complete authentication ({0}).",
 | 
											
												
													
														|  | 
 |  | +                                                                                       string.Join(",", allowedAuthenticationMethods)));
 | 
											
												
													
														|  |                  return false;
 |  |                  return false;
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -            foreach (var authenticationMethod in GetOrderedAuthenticationMethods(authenticationState, matchingAuthenticationMethods))
 |  | 
 | 
											
												
													
														|  | 
 |  | +            foreach (var authenticationMethod in authenticationState.GetActiveAuthenticationMethods(matchingAuthenticationMethods))
 | 
											
												
													
														|  |              {
 |  |              {
 | 
											
												
													
														|  | -                if (authenticationState.FailedAuthenticationMethods.Contains(authenticationMethod))
 |  | 
 | 
											
												
													
														|  | -                    continue;
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -                // when the authentication method was previously executed, then skip the authentication
 |  | 
 | 
											
												
													
														|  | -                // method as long as there's another authentication method to try; this is done to avoid
 |  | 
 | 
											
												
													
														|  | -                // a stack overflow for servers that do not update the list of allowed authentication
 |  | 
 | 
											
												
													
														|  | 
 |  | +                // guard against a stack overlow for servers that do not update the list of allowed authentication
 | 
											
												
													
														|  |                  // methods after a partial success
 |  |                  // methods after a partial success
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -                if (!authenticationState.ExecutedAuthenticationMethods.Contains(authenticationMethod))
 |  | 
 | 
											
												
													
														|  | 
 |  | +                if (authenticationState.GetPartialSuccessCount(authenticationMethod) >= _partialSuccessLimit)
 | 
											
												
													
														|  |                  {
 |  |                  {
 | 
											
												
													
														|  | -                    // update state to reflect previosuly executed authentication methods
 |  | 
 | 
											
												
													
														|  | -                    authenticationState.ExecutedAuthenticationMethods.Add(authenticationMethod);
 |  | 
 | 
											
												
													
														|  | 
 |  | +                    // TODO Get list of all authentication methods that have reached the partial success limit?
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                    authenticationException = new SshAuthenticationException(string.Format("Reached authentication attempt limit for method ({0}).",
 | 
											
												
													
														|  | 
 |  | +                                                                                           authenticationMethod.Name));
 | 
											
												
													
														|  | 
 |  | +                    continue;
 | 
											
												
													
														|  |                  }
 |  |                  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |                  var authenticationResult = authenticationMethod.Authenticate(session);
 |  |                  var authenticationResult = authenticationMethod.Authenticate(session);
 | 
											
												
													
														|  |                  switch (authenticationResult)
 |  |                  switch (authenticationResult)
 | 
											
												
													
														|  |                  {
 |  |                  {
 | 
											
												
													
														|  |                      case AuthenticationResult.PartialSuccess:
 |  |                      case AuthenticationResult.PartialSuccess:
 | 
											
												
													
														|  | 
 |  | +                        authenticationState.RecordPartialSuccess(authenticationMethod);
 | 
											
												
													
														|  |                          if (TryAuthenticate(session, authenticationState, authenticationMethod.AllowedAuthentications, ref authenticationException))
 |  |                          if (TryAuthenticate(session, authenticationState, authenticationMethod.AllowedAuthentications, ref authenticationException))
 | 
											
												
													
														|  |                          {
 |  |                          {
 | 
											
												
													
														|  |                              authenticationResult = AuthenticationResult.Success;
 |  |                              authenticationResult = AuthenticationResult.Success;
 | 
											
												
													
														|  |                          }
 |  |                          }
 | 
											
												
													
														|  |                          break;
 |  |                          break;
 | 
											
												
													
														|  |                      case AuthenticationResult.Failure:
 |  |                      case AuthenticationResult.Failure:
 | 
											
												
													
														|  | -                        authenticationState.FailedAuthenticationMethods.Add(authenticationMethod);
 |  | 
 | 
											
												
													
														|  | 
 |  | +                        authenticationState.RecordFailure(authenticationMethod);
 | 
											
												
													
														|  |                          authenticationException = new SshAuthenticationException(string.Format("Permission denied ({0}).", authenticationMethod.Name));
 |  |                          authenticationException = new SshAuthenticationException(string.Format("Permission denied ({0}).", authenticationMethod.Name));
 | 
											
												
													
														|  |                          break;
 |  |                          break;
 | 
											
												
													
														|  |                      case AuthenticationResult.Success:
 |  |                      case AuthenticationResult.Success:
 | 
											
										
											
												
													
														|  | @@ -106,85 +139,151 @@ namespace Renci.SshNet
 | 
											
												
													
														|  |              return false;
 |  |              return false;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -        private static List<IAuthenticationMethod> GetAllowedAuthenticationMethodsThatAreSupported(AuthenticationState authenticationState,
 |  | 
 | 
											
												
													
														|  | -                                                                                                   string[] allowedAuthenticationMethods)
 |  | 
 | 
											
												
													
														|  | 
 |  | +        private class AuthenticationState
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
												
													
														|  | -            var result = new List<IAuthenticationMethod>();
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -            foreach (var supportedAuthenticationMethod in authenticationState.SupportedAuthenticationMethods)
 |  | 
 | 
											
												
													
														|  | -            {
 |  | 
 | 
											
												
													
														|  | -                var nameOfSupportedAuthenticationMethod = supportedAuthenticationMethod.Name;
 |  | 
 | 
											
												
													
														|  | 
 |  | +            private readonly IList<IAuthenticationMethod> _supportedAuthenticationMethods;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -                for (var i = 0; i < allowedAuthenticationMethods.Length; i++)
 |  | 
 | 
											
												
													
														|  | -                {
 |  | 
 | 
											
												
													
														|  | -                    if (allowedAuthenticationMethods[i] == nameOfSupportedAuthenticationMethod)
 |  | 
 | 
											
												
													
														|  | -                    {
 |  | 
 | 
											
												
													
														|  | -                        result.Add(supportedAuthenticationMethod);
 |  | 
 | 
											
												
													
														|  | -                        break;
 |  | 
 | 
											
												
													
														|  | -                    }
 |  | 
 | 
											
												
													
														|  | -                }
 |  | 
 | 
											
												
													
														|  | -            }
 |  | 
 | 
											
												
													
														|  | 
 |  | +            /// <summary>
 | 
											
												
													
														|  | 
 |  | +            /// Records if a given <see cref="IAuthenticationMethod"/> has been tried, and how many times this resulted
 | 
											
												
													
														|  | 
 |  | +            /// in <see cref="AuthenticationResult.PartialSuccess"/>.
 | 
											
												
													
														|  | 
 |  | +            /// </summary>
 | 
											
												
													
														|  | 
 |  | +            /// <remarks>
 | 
											
												
													
														|  | 
 |  | +            /// When there's no entry for a given <see cref="IAuthenticationMethod"/>, then it was never tried.
 | 
											
												
													
														|  | 
 |  | +            /// </remarks>
 | 
											
												
													
														|  | 
 |  | +            private readonly Dictionary<IAuthenticationMethod, int> _authenticationMethodPartialSuccessRegister;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -            return result;
 |  | 
 | 
											
												
													
														|  | -        }
 |  | 
 | 
											
												
													
														|  | 
 |  | +            /// <summary>
 | 
											
												
													
														|  | 
 |  | +            /// Holds the list of authentications methods that failed.
 | 
											
												
													
														|  | 
 |  | +            /// </summary>
 | 
											
												
													
														|  | 
 |  | +            private readonly List<IAuthenticationMethod> _failedAuthenticationMethods;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -        private static IEnumerable<IAuthenticationMethod> GetOrderedAuthenticationMethods(AuthenticationState authenticationState, List<IAuthenticationMethod> matchingAuthenticationMethods)
 |  | 
 | 
											
												
													
														|  | -        {
 |  | 
 | 
											
												
													
														|  | -            var skippedAuthenticationMethods = new List<IAuthenticationMethod>();
 |  | 
 | 
											
												
													
														|  | 
 |  | +            public AuthenticationState(IList<IAuthenticationMethod> supportedAuthenticationMethods)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                _supportedAuthenticationMethods = supportedAuthenticationMethods;
 | 
											
												
													
														|  | 
 |  | +                _failedAuthenticationMethods = new List<IAuthenticationMethod>();
 | 
											
												
													
														|  | 
 |  | +                _authenticationMethodPartialSuccessRegister = new Dictionary<IAuthenticationMethod, int>();
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -            for (var i = 0; i < matchingAuthenticationMethods.Count; i++)
 |  | 
 | 
											
												
													
														|  | 
 |  | +            /// <summary>
 | 
											
												
													
														|  | 
 |  | +            /// Records a <see cref="AuthenticationResult.Failure"/> authentication attempt for the specified
 | 
											
												
													
														|  | 
 |  | +            /// <see cref="IAuthenticationMethod"/> .
 | 
											
												
													
														|  | 
 |  | +            /// </summary>
 | 
											
												
													
														|  | 
 |  | +            /// <param name="authenticationMethod">An <see cref="IAuthenticationMethod"/> for which to record the result of an authentication attempt.</param>
 | 
											
												
													
														|  | 
 |  | +            public void RecordFailure(IAuthenticationMethod authenticationMethod)
 | 
											
												
													
														|  |              {
 |  |              {
 | 
											
												
													
														|  | -                var authenticationMethod = matchingAuthenticationMethods[i];
 |  | 
 | 
											
												
													
														|  | 
 |  | +                _failedAuthenticationMethods.Add(authenticationMethod);
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -                if (authenticationState.ExecutedAuthenticationMethods.Contains(authenticationMethod))
 |  | 
 | 
											
												
													
														|  | 
 |  | +            /// <summary>
 | 
											
												
													
														|  | 
 |  | +            /// Records a <see cref="AuthenticationResult.PartialSuccess"/> authentication attempt for the specified
 | 
											
												
													
														|  | 
 |  | +            /// <see cref="IAuthenticationMethod"/> .
 | 
											
												
													
														|  | 
 |  | +            /// </summary>
 | 
											
												
													
														|  | 
 |  | +            /// <param name="authenticationMethod">An <see cref="IAuthenticationMethod"/> for which to record the result of an authentication attempt.</param>
 | 
											
												
													
														|  | 
 |  | +            public void RecordPartialSuccess(IAuthenticationMethod authenticationMethod)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                int partialSuccessCount;
 | 
											
												
													
														|  | 
 |  | +                if (_authenticationMethodPartialSuccessRegister.TryGetValue(authenticationMethod, out partialSuccessCount))
 | 
											
												
													
														|  |                  {
 |  |                  {
 | 
											
												
													
														|  | -                    skippedAuthenticationMethods.Add(authenticationMethod);
 |  | 
 | 
											
												
													
														|  | -                    continue;
 |  | 
 | 
											
												
													
														|  | 
 |  | +                    _authenticationMethodPartialSuccessRegister[authenticationMethod] = ++partialSuccessCount;
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +                else
 | 
											
												
													
														|  | 
 |  | +                {
 | 
											
												
													
														|  | 
 |  | +                    _authenticationMethodPartialSuccessRegister.Add(authenticationMethod, 1);
 | 
											
												
													
														|  |                  }
 |  |                  }
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -                yield return authenticationMethod;
 |  | 
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -            foreach (var authenticationMethod in skippedAuthenticationMethods)
 |  | 
 | 
											
												
													
														|  | -                yield return authenticationMethod;
 |  | 
 | 
											
												
													
														|  | -        }
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -        private class AuthenticationState
 |  | 
 | 
											
												
													
														|  | -        {
 |  | 
 | 
											
												
													
														|  | -            private readonly IList<IAuthenticationMethod> _supportedAuthenticationMethods;
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -            public AuthenticationState(IList<IAuthenticationMethod> supportedAuthenticationMethods)
 |  | 
 | 
											
												
													
														|  | 
 |  | +            /// <summary>
 | 
											
												
													
														|  | 
 |  | +            /// Returns the number of times an authentication attempt with the specified <see cref="IAuthenticationMethod"/>
 | 
											
												
													
														|  | 
 |  | +            /// has resulted in <see cref="AuthenticationResult.PartialSuccess"/>.
 | 
											
												
													
														|  | 
 |  | +            /// </summary>
 | 
											
												
													
														|  | 
 |  | +            /// <param name="authenticationMethod">An <see cref="IAuthenticationMethod"/>.</param>
 | 
											
												
													
														|  | 
 |  | +            /// <returns>
 | 
											
												
													
														|  | 
 |  | +            /// The number of times an authentication attempt with the specified <see cref="IAuthenticationMethod"/>
 | 
											
												
													
														|  | 
 |  | +            /// has resulted in <see cref="AuthenticationResult.PartialSuccess"/>.
 | 
											
												
													
														|  | 
 |  | +            /// </returns>
 | 
											
												
													
														|  | 
 |  | +            public int GetPartialSuccessCount(IAuthenticationMethod authenticationMethod)
 | 
											
												
													
														|  |              {
 |  |              {
 | 
											
												
													
														|  | -                _supportedAuthenticationMethods = supportedAuthenticationMethods;
 |  | 
 | 
											
												
													
														|  | -                ExecutedAuthenticationMethods = new List<IAuthenticationMethod>();
 |  | 
 | 
											
												
													
														|  | -                FailedAuthenticationMethods = new List<IAuthenticationMethod>();
 |  | 
 | 
											
												
													
														|  | 
 |  | +                int partialSuccessCount;
 | 
											
												
													
														|  | 
 |  | +                if (_authenticationMethodPartialSuccessRegister.TryGetValue(authenticationMethod, out partialSuccessCount))
 | 
											
												
													
														|  | 
 |  | +                {
 | 
											
												
													
														|  | 
 |  | +                    return partialSuccessCount;
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +                return 0;
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |              /// <summary>
 |  |              /// <summary>
 | 
											
												
													
														|  | -            /// Gets the list of authentication methods that were previously executed.
 |  | 
 | 
											
												
													
														|  | 
 |  | +            /// Returns a list of supported authentication methods that match one of the specified allowed authentication
 | 
											
												
													
														|  | 
 |  | +            /// methods.
 | 
											
												
													
														|  |              /// </summary>
 |  |              /// </summary>
 | 
											
												
													
														|  | -            /// <value>
 |  | 
 | 
											
												
													
														|  | -            /// The list of authentication methods that were previously executed.
 |  | 
 | 
											
												
													
														|  | -            /// </value>
 |  | 
 | 
											
												
													
														|  | -            public IList<IAuthenticationMethod> ExecutedAuthenticationMethods { get; private set; }
 |  | 
 | 
											
												
													
														|  | 
 |  | +            /// <param name="allowedAuthenticationMethods">A list of allowed authentication methods.</param>
 | 
											
												
													
														|  | 
 |  | +            /// <returns>
 | 
											
												
													
														|  | 
 |  | +            /// A list of supported authentication methods that match one of the specified allowed authentication methods.
 | 
											
												
													
														|  | 
 |  | +            /// </returns>
 | 
											
												
													
														|  | 
 |  | +            /// <remarks>
 | 
											
												
													
														|  | 
 |  | +            /// The authentication methods are returned in the order in which they were specified in the list that was
 | 
											
												
													
														|  | 
 |  | +            /// used to initialize the current <see cref="AuthenticationState"/> instance.
 | 
											
												
													
														|  | 
 |  | +            /// </remarks>
 | 
											
												
													
														|  | 
 |  | +            public List<IAuthenticationMethod> GetSupportedAuthenticationMethods(string[] allowedAuthenticationMethods)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                var result = new List<IAuthenticationMethod>();
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -            /// <summary>
 |  | 
 | 
											
												
													
														|  | -            /// Gets the list of authentications methods that failed.
 |  | 
 | 
											
												
													
														|  | -            /// </summary>
 |  | 
 | 
											
												
													
														|  | -            /// <value>
 |  | 
 | 
											
												
													
														|  | -            /// The list of authentications methods that failed.
 |  | 
 | 
											
												
													
														|  | -            /// </value>
 |  | 
 | 
											
												
													
														|  | -            public IList<IAuthenticationMethod> FailedAuthenticationMethods { get; private set; }
 |  | 
 | 
											
												
													
														|  | 
 |  | +                foreach (var supportedAuthenticationMethod in _supportedAuthenticationMethods)
 | 
											
												
													
														|  | 
 |  | +                {
 | 
											
												
													
														|  | 
 |  | +                    var nameOfSupportedAuthenticationMethod = supportedAuthenticationMethod.Name;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                    for (var i = 0; i < allowedAuthenticationMethods.Length; i++)
 | 
											
												
													
														|  | 
 |  | +                    {
 | 
											
												
													
														|  | 
 |  | +                        if (allowedAuthenticationMethods[i] == nameOfSupportedAuthenticationMethod)
 | 
											
												
													
														|  | 
 |  | +                        {
 | 
											
												
													
														|  | 
 |  | +                            result.Add(supportedAuthenticationMethod);
 | 
											
												
													
														|  | 
 |  | +                            break;
 | 
											
												
													
														|  | 
 |  | +                        }
 | 
											
												
													
														|  | 
 |  | +                    }
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                return result;
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |              /// <summary>
 |  |              /// <summary>
 | 
											
												
													
														|  | -            /// Gets the list of supported authentication methods.
 |  | 
 | 
											
												
													
														|  | 
 |  | +            /// Returns the authentication methods from the specified list that have not yet failed.
 | 
											
												
													
														|  |              /// </summary>
 |  |              /// </summary>
 | 
											
												
													
														|  | -            /// <value>
 |  | 
 | 
											
												
													
														|  | -            /// The list of supported authentication methods.
 |  | 
 | 
											
												
													
														|  | -            /// </value>
 |  | 
 | 
											
												
													
														|  | -            public IList<IAuthenticationMethod> SupportedAuthenticationMethods
 |  | 
 | 
											
												
													
														|  | 
 |  | +            /// <param name="matchingAuthenticationMethods">A list of authentication methods.</param>
 | 
											
												
													
														|  | 
 |  | +            /// <returns>
 | 
											
												
													
														|  | 
 |  | +            /// The authentication methods from <paramref name="matchingAuthenticationMethods"/> that have not yet failed.
 | 
											
												
													
														|  | 
 |  | +            /// </returns>
 | 
											
												
													
														|  | 
 |  | +            /// <remarks>
 | 
											
												
													
														|  | 
 |  | +            /// <para>
 | 
											
												
													
														|  | 
 |  | +            /// This method first returns the authentication methods that have not yet been executed, and only then
 | 
											
												
													
														|  | 
 |  | +            /// returns those for which an authentication attempt resulted in a <see cref="AuthenticationResult.PartialSuccess"/>.
 | 
											
												
													
														|  | 
 |  | +            /// </para>
 | 
											
												
													
														|  | 
 |  | +            /// <para>
 | 
											
												
													
														|  | 
 |  | +            /// Any <see cref="IAuthenticationMethod"/> that has failed is skipped.
 | 
											
												
													
														|  | 
 |  | +            /// </para>
 | 
											
												
													
														|  | 
 |  | +            /// </remarks>
 | 
											
												
													
														|  | 
 |  | +            public IEnumerable<IAuthenticationMethod> GetActiveAuthenticationMethods(List<IAuthenticationMethod> matchingAuthenticationMethods)
 | 
											
												
													
														|  |              {
 |  |              {
 | 
											
												
													
														|  | -                get { return _supportedAuthenticationMethods; }
 |  | 
 | 
											
												
													
														|  | 
 |  | +                var skippedAuthenticationMethods = new List<IAuthenticationMethod>();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                for (var i = 0; i < matchingAuthenticationMethods.Count; i++)
 | 
											
												
													
														|  | 
 |  | +                {
 | 
											
												
													
														|  | 
 |  | +                    var authenticationMethod = matchingAuthenticationMethods[i];
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                    // skip authentication methods that have already failed
 | 
											
												
													
														|  | 
 |  | +                    if (_failedAuthenticationMethods.Contains(authenticationMethod))
 | 
											
												
													
														|  | 
 |  | +                        continue;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                    // delay use of authentication methods that had a PartialSuccess result
 | 
											
												
													
														|  | 
 |  | +                    if (_authenticationMethodPartialSuccessRegister.ContainsKey(authenticationMethod))
 | 
											
												
													
														|  | 
 |  | +                    {
 | 
											
												
													
														|  | 
 |  | +                        skippedAuthenticationMethods.Add(authenticationMethod);
 | 
											
												
													
														|  | 
 |  | +                        continue;
 | 
											
												
													
														|  | 
 |  | +                    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                    yield return authenticationMethod;
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                foreach (var authenticationMethod in skippedAuthenticationMethods)
 | 
											
												
													
														|  | 
 |  | +                    yield return authenticationMethod;
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      }
 |  |      }
 |