Пример #1
0
        /// <inheritdoc/>
        public async Task <LoginResultData> Login(
            UriString host,
            string username,
            string password)
        {
            Guard.ArgumentNotNull(host, nameof(host));
            Guard.ArgumentNotNullOrWhiteSpace(username, nameof(username));
            Guard.ArgumentNotNullOrWhiteSpace(password, nameof(password));

            // Start by saving the username and password, these will be used by the `IGitHubClient`
            // until an authorization token has been created and acquired:
            keychain.Connect(host);
            keychain.SetCredentials(new Credential(host, username, password));

            try
            {
                var loginResultData = await TryLogin(host, username, password);

                if (loginResultData.Code == LoginResultCodes.Success || loginResultData.Code == LoginResultCodes.CodeRequired)
                {
                    if (string.IsNullOrEmpty(loginResultData.Token))
                    {
                        throw new InvalidOperationException("Returned token is null or empty");
                    }

                    if (loginResultData.Code == LoginResultCodes.Success)
                    {
                        username = await RetrieveUsername(loginResultData, username);
                    }

                    keychain.SetToken(host, loginResultData.Token, username);

                    if (loginResultData.Code == LoginResultCodes.Success)
                    {
                        await keychain.Save(host);
                    }

                    return(loginResultData);
                }

                return(loginResultData);
            }
            catch (Exception e)
            {
                logger.Warning(e, "Login Exception");

                await keychain.Clear(host, false);

                return(new LoginResultData(LoginResultCodes.Failed, Localization.LoginFailed, host));
            }
        }
Пример #2
0
        /// <inheritdoc/>
        public async Task <LoginResult> Login(
            HostAddress hostAddress,
            IGitHubClient client,
            string userName,
            string password)
        {
            Guard.ArgumentNotNull(hostAddress, nameof(hostAddress));
            Guard.ArgumentNotNull(client, nameof(client));
            Guard.ArgumentNotEmptyString(userName, nameof(userName));
            Guard.ArgumentNotEmptyString(password, nameof(password));

            // Start by saving the username and password, these will be used by the `IGitHubClient`
            // until an authorization token has been created and acquired:
            await keychain.Save(userName, password, hostAddress).ConfigureAwait(false);

            var newAuth = new NewAuthorization
            {
                Scopes      = requestedScopes,
                Note        = authorizationNote,
                Fingerprint = fingerprint,
            };

            ApplicationAuthorization auth = null;

            do
            {
                try
                {
                    auth = await CreateAndDeleteExistingApplicationAuthorization(client, newAuth, null)
                           .ConfigureAwait(false);

                    EnsureNonNullAuthorization(auth);
                }
                catch (TwoFactorAuthorizationException e)
                {
                    auth = await HandleTwoFactorAuthorization(hostAddress, client, newAuth, e)
                           .ConfigureAwait(false);
                }
                catch (Exception e)
                {
                    // Some enterpise instances don't support OAUTH, so fall back to using the
                    // supplied password - on intances that don't support OAUTH the user should
                    // be using a personal access token as the password.
                    if (EnterpriseWorkaround(hostAddress, e))
                    {
                        auth = new ApplicationAuthorization(password);
                    }
                    else
                    {
                        await keychain.Delete(hostAddress).ConfigureAwait(false);

                        throw;
                    }
                }
            } while (auth == null);

            await keychain.Save(userName, auth.Token, hostAddress).ConfigureAwait(false);

            return(await ReadUserWithRetry(client).ConfigureAwait(false));
        }
Пример #3
0
        /// <inheritdoc/>
        public async Task <User> Login(
            HostAddress hostAddress,
            IGitHubClient client,
            string userName,
            string password)
        {
            Guard.ArgumentNotNull(hostAddress, nameof(hostAddress));
            Guard.ArgumentNotNull(client, nameof(client));
            Guard.ArgumentNotEmptyString(userName, nameof(userName));
            Guard.ArgumentNotEmptyString(password, nameof(password));

            // Start by saving the username and password, these will be used by the `IGitHubClient`
            // until an authorization token has been created and acquired:
            await keychain.Save(userName, password, hostAddress).ConfigureAwait(false);

            var newAuth = new NewAuthorization
            {
                Scopes      = scopes,
                Note        = authorizationNote,
                Fingerprint = fingerprint,
            };

            ApplicationAuthorization auth = null;

            do
            {
                try
                {
                    auth = await CreateAndDeleteExistingApplicationAuthorization(client, newAuth, null)
                           .ConfigureAwait(false);

                    EnsureNonNullAuthorization(auth);
                }
                catch (TwoFactorAuthorizationException e)
                {
                    auth = await HandleTwoFactorAuthorization(hostAddress, client, newAuth, e)
                           .ConfigureAwait(false);
                }
                catch (Exception e)
                {
                    // Some enterpise instances don't support OAUTH, so fall back to using the
                    // supplied password - on intances that don't support OAUTH the user should
                    // be using a personal access token as the password.
                    if (EnterpriseWorkaround(hostAddress, e))
                    {
                        auth = new ApplicationAuthorization(password);
                    }
                    else
                    {
                        await keychain.Delete(hostAddress).ConfigureAwait(false);

                        throw;
                    }
                }
            } while (auth == null);

            await keychain.Save(userName, auth.Token, hostAddress).ConfigureAwait(false);

            var retry = 0;

            while (true)
            {
                try
                {
                    return(await client.User.Current().ConfigureAwait(false));
                }
                catch (AuthorizationException)
                {
                    if (retry++ == 3)
                    {
                        throw;
                    }
                }

                // It seems that attempting to use a token immediately sometimes fails, retry a few
                // times with a delay of of 1s to allow the token to propagate.
                await Task.Delay(1000);
            }
        }
Пример #4
0
        /// <inheritdoc/>
        public async Task <LoginResultData> Login(
            UriString host,
            IGitHubClient client,
            string username,
            string password)
        {
            Guard.ArgumentNotNull(host, nameof(host));
            Guard.ArgumentNotNull(client, nameof(client));
            Guard.ArgumentNotNullOrWhiteSpace(username, nameof(username));
            Guard.ArgumentNotNullOrWhiteSpace(password, nameof(password));

            // Start by saving the username and password, these will be used by the `IGitHubClient`
            // until an authorization token has been created and acquired:
            keychain.Connect(host);
            keychain.SetCredentials(new Credential(host, username, password));

            var newAuth = new NewAuthorization
            {
                Scopes      = scopes,
                Note        = authorizationNote,
                Fingerprint = fingerprint,
            };

            ApplicationAuthorization auth = null;

            try
            {
                logger.Info("Login Username:{0}", username);

                auth = await CreateAndDeleteExistingApplicationAuthorization(client, newAuth, null);

                EnsureNonNullAuthorization(auth);
            }
            catch (TwoFactorAuthorizationException e)
            {
                LoginResultCodes result;
                if (e is TwoFactorRequiredException)
                {
                    result = LoginResultCodes.CodeRequired;
                    logger.Debug("2FA TwoFactorAuthorizationException: {0} {1}", LoginResultCodes.CodeRequired, e.Message);
                }
                else
                {
                    result = LoginResultCodes.CodeFailed;
                    logger.Error(e, "2FA TwoFactorAuthorizationException: {0} {1}", LoginResultCodes.CodeRequired, e.Message);
                }

                return(new LoginResultData(result, e.Message, client, host, newAuth));
            }
            catch (LoginAttemptsExceededException e)
            {
                logger.Warning(e, "Login LoginAttemptsExceededException: {0}", e.Message);

                await keychain.Clear(host, false);

                return(new LoginResultData(LoginResultCodes.LockedOut, Localization.LockedOut, host));
            }
            catch (ApiValidationException e)
            {
                logger.Warning(e, "Login ApiValidationException: {0}", e.Message);

                var message = e.ApiError.FirstErrorMessageSafe();
                await keychain.Clear(host, false);

                return(new LoginResultData(LoginResultCodes.Failed, message, host));
            }
            catch (Exception e)
            {
                logger.Warning(e, "Login Exception");

                // Some enterprise instances don't support OAUTH, so fall back to using the
                // supplied password - on instances that don't support OAUTH the user should
                // be using a personal access token as the password.
                if (EnterpriseWorkaround(host, e))
                {
                    auth = new ApplicationAuthorization(password);
                }
                else
                {
                    await keychain.Clear(host, false);

                    return(new LoginResultData(LoginResultCodes.Failed, Localization.LoginFailed, host));
                }
            }

            keychain.SetToken(host, auth.Token);
            await keychain.Save(host);

            return(new LoginResultData(LoginResultCodes.Success, "Success", host));
        }