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