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