public async Task Does_not_cache_login_attempts()
        {
            var cacheProvider   = Caches.NewInMemoryCacheProvider().Build();
            var requestExecutor = Substitute.For <IRequestExecutor>();

            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            var authResponse = @"
{
  ""account"": {
    ""href"" : ""https://api.stormpath.com/v1/accounts/5BedLIvyfLjdKKEEXAMPLE""
  }
}";

            // POST returns auth response
            requestExecutor
            .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any <CancellationToken>())
            .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), authResponse, "application/json", transportError: false) as IHttpResponse));

            var request       = new UsernamePasswordRequest("foo", "bar", null, null) as IAuthenticationRequest;
            var authenticator = new BasicAuthenticator(this.dataStore);

            var result1 = await authenticator.AuthenticateAsync("/loginAttempts", request, null, CancellationToken.None);

            var result2 = await authenticator.AuthenticateAsync("/loginAttempts", request, null, CancellationToken.None);

            // Not cached
            await this.dataStore.RequestExecutor.Received(2).ExecuteAsync(
                Arg.Any <IHttpRequest>(),
                Arg.Any <CancellationToken>());
        }
Ejemplo n.º 2
0
        private async Task <AuthenticationResult> AcquireTokenByUsernamePasswordAsync(IEnumerable <string> scopes, UsernamePasswordInput usernamePasswordInput)
        {
            Authority authority     = Instance.Authority.CreateAuthority(ServiceBundle, Authority, ValidateAuthority);
            var       requestParams = CreateRequestParameters(authority, scopes, null, UserTokenCache);
            var       handler       = new UsernamePasswordRequest(
                ServiceBundle,
                requestParams,
                ApiEvent.ApiIds.AcquireTokenWithScopeUser,
                usernamePasswordInput);

            return(await handler.RunAsync(CancellationToken.None).ConfigureAwait(false));
        }
Ejemplo n.º 3
0
        public async Task <AuthenticationResult> ExecuteAsync(
            AcquireTokenCommonParameters commonParameters,
            AcquireTokenByUsernamePasswordParameters usernamePasswordParameters,
            CancellationToken cancellationToken)
        {
            var requestContext = CreateRequestContextAndLogVersionInfo(commonParameters.CorrelationId);

            var requestParams = _publicClientApplication.CreateRequestParameters(
                commonParameters,
                requestContext,
                _publicClientApplication.UserTokenCacheInternal);

            var handler = new UsernamePasswordRequest(
                ServiceBundle,
                requestParams,
                usernamePasswordParameters);

            return(await handler.RunAsync(cancellationToken).ConfigureAwait(false));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Do the authentication part of Tor's SOCKS5 protocol.
        /// </summary>
        /// <param name="isolateStream">Whether random username/password should be used for authentication and thus effectively create a new Tor circuit.</param>
        /// <remarks>Tor process must be started with enabled <c>IsolateSOCKSAuth</c> option. It's ON by default.</remarks>
        /// <seealso href="https://www.torproject.org/docs/tor-manual.html.en"/>
        /// <seealso href="https://linux.die.net/man/1/tor">For <c>IsolateSOCKSAuth</c> option explanation.</seealso>
        /// <seealso href="https://gitweb.torproject.org/torspec.git/tree/socks-extensions.txt#n35"/>
        public async Task HandshakeAsync(bool isolateStream = false, CancellationToken cancellationToken = default)
        {
            Logger.LogDebug($"> {nameof(isolateStream)}={isolateStream}");

            // https://github.com/torproject/torspec/blob/master/socks-extensions.txt
            // The "NO AUTHENTICATION REQUIRED" (SOCKS5) authentication method [00] is
            // supported; and as of Tor 0.2.3.2 - alpha, the "USERNAME/PASSWORD"(SOCKS5)
            // authentication method[02] is supported too, and used as a method to
            // implement stream isolation.As an extension to support some broken clients,
            // we allow clients to pass "USERNAME/PASSWORD" authentication message to us
            // even if no authentication was selected.Furthermore, we allow
            // username / password fields of this message to be empty. This technically
            // violates RFC1929[4], but ensures interoperability with somewhat broken
            // SOCKS5 client implementations.
            var methods = new MethodsField(isolateStream ? MethodField.UsernamePassword : MethodField.NoAuthenticationRequired);

            byte[] receiveBuffer = await SendRequestAsync(new VersionMethodRequest(methods), cancellationToken).ConfigureAwait(false);

            var methodSelection = new MethodSelectionResponse(receiveBuffer);

            if (methodSelection.Ver != VerField.Socks5)
            {
                throw new NotSupportedException($"SOCKS{methodSelection.Ver.Value} not supported. Only SOCKS5 is supported.");
            }
            else if (methodSelection.Method == MethodField.NoAcceptableMethods)
            {
                // https://www.ietf.org/rfc/rfc1928.txt
                // If the selected METHOD is X'FF', none of the methods listed by the
                // client are acceptable, and the client MUST close the connection.
                DisposeTcpClient();
                throw new NotSupportedException("Tor's SOCKS5 proxy does not support any of the client's authentication methods.");
            }
            else if (methodSelection.Method == MethodField.UsernamePassword)
            {
                // https://tools.ietf.org/html/rfc1929#section-2
                // Once the SOCKS V5 server has started, and the client has selected the
                // Username / Password Authentication protocol, the Username / Password
                // sub-negotiation begins. This begins with the client producing a
                // Username / Password request:
                var identity = RandomString.CapitalAlphaNumeric(21);
                var uName    = new UNameField(uName: identity);
                var passwd   = new PasswdField(password: identity);
                var usernamePasswordRequest = new UsernamePasswordRequest(uName, passwd);

                receiveBuffer = await SendRequestAsync(usernamePasswordRequest, cancellationToken).ConfigureAwait(false);

                var userNamePasswordResponse = new UsernamePasswordResponse(receiveBuffer);

                if (userNamePasswordResponse.Ver != usernamePasswordRequest.Ver)
                {
                    throw new NotSupportedException($"Authentication version {userNamePasswordResponse.Ver.Value} not supported. Only version {usernamePasswordRequest.Ver} is supported.");
                }

                if (!userNamePasswordResponse.Status.IsSuccess())                 // Tor authentication is different, this will never happen;
                {
                    // https://tools.ietf.org/html/rfc1929#section-2
                    // A STATUS field of X'00' indicates success. If the server returns a
                    // `failure' (STATUS value other than X'00') status, it MUST close the
                    // connection.
                    DisposeTcpClient();
                    throw new InvalidOperationException("Wrong username and/or password.");
                }
            }

            Logger.LogDebug("<");
        }
        /// <summary>
        /// IsolateSOCKSAuth must be on (on by default)
        /// https://www.torproject.org/docs/tor-manual.html.en
        /// https://gitweb.torproject.org/torspec.git/tree/socks-extensions.txt#n35
        /// </summary>
        /// <param name="identity">Isolates streams by identity. If identity is empty string, it won't isolate stream.</param>
        internal async Task HandshakeAsync(string identity)
        {
            if (TorSocks5EndPoint is null)
            {
                return;
            }

            Guard.NotNull(nameof(identity), identity);

            MethodsField methods = string.IsNullOrWhiteSpace(identity)
                                ? new MethodsField(MethodField.NoAuthenticationRequired)
                                : new MethodsField(MethodField.UsernamePassword);

            var sendBuffer = new VersionMethodRequest(methods).ToBytes();

            var receiveBuffer = await SendAsync(sendBuffer, 2).ConfigureAwait(false);

            var methodSelection = new MethodSelectionResponse();

            methodSelection.FromBytes(receiveBuffer);
            if (methodSelection.Ver != VerField.Socks5)
            {
                throw new NotSupportedException($"SOCKS{methodSelection.Ver.Value} not supported. Only SOCKS5 is supported.");
            }
            if (methodSelection.Method == MethodField.NoAcceptableMethods)
            {
                // https://www.ietf.org/rfc/rfc1928.txt
                // If the selected METHOD is X'FF', none of the methods listed by the
                // client are acceptable, and the client MUST close the connection.
                DisposeTcpClient();
                throw new NotSupportedException("Tor's SOCKS5 proxy does not support any of the client's authentication methods.");
            }
            if (methodSelection.Method == MethodField.UsernamePassword)
            {
                // https://tools.ietf.org/html/rfc1929#section-2
                // Once the SOCKS V5 server has started, and the client has selected the
                // Username / Password Authentication protocol, the Username / Password
                // subnegotiation begins. This begins with the client producing a
                // Username / Password request:
                var username = identity;
                var password = identity;
                var uName    = new UNameField(username);
                var passwd   = new PasswdField(password);
                var usernamePasswordRequest = new UsernamePasswordRequest(uName, passwd);
                sendBuffer = usernamePasswordRequest.ToBytes();

                Array.Clear(receiveBuffer, 0, receiveBuffer.Length);
                receiveBuffer = await SendAsync(sendBuffer, 2).ConfigureAwait(false);

                var userNamePasswordResponse = new UsernamePasswordResponse();
                userNamePasswordResponse.FromBytes(receiveBuffer);
                if (userNamePasswordResponse.Ver != usernamePasswordRequest.Ver)
                {
                    throw new NotSupportedException($"Authentication version {userNamePasswordResponse.Ver.Value} not supported. Only version {usernamePasswordRequest.Ver} is supported.");
                }

                if (!userNamePasswordResponse.Status.IsSuccess())                 // Tor authentication is different, this will never happen;
                {
                    // https://tools.ietf.org/html/rfc1929#section-2
                    // A STATUS field of X'00' indicates success. If the server returns a
                    // `failure' (STATUS value other than X'00') status, it MUST close the
                    // connection.
                    DisposeTcpClient();
                    throw new InvalidOperationException("Wrong username and/or password.");
                }
            }
        }
Ejemplo n.º 6
0
        IAuthenticationResult IApplicationSync.AuthenticateAccount(string username, string password)
        {
            var request = new UsernamePasswordRequest(username, password, null, null) as IAuthenticationRequest;

            return(this.AuthenticateAccount(request));
        }
        Task <IAuthenticationResult> IApplication.AuthenticateAccountAsync(string username, string password, CancellationToken cancellationToken)
        {
            var request = new UsernamePasswordRequest(username, password, null, null) as IAuthenticationRequest;

            return(this.AsInterface.AuthenticateAccountAsync(request, cancellationToken));
        }