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>()); }
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)); }
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)); }
/// <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."); } } }
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)); }