/// <inheritdoc/> public async Task <AuthenticationResult> AcquireToken(TargetUri targetUri, string username, string password, AuthenticationResultType resultType, TokenScope scope) { if (resultType == AuthenticationResultType.TwoFactor) { // a previous attempt to aquire a token failed in a way that suggests the user has // Bitbucket 2FA turned on. so attempt to run the OAuth dance... OAuth.OAuthAuthenticator oauth = new OAuth.OAuthAuthenticator(); try { var result = await oauth.GetAuthAsync(targetUri, scope, CancellationToken.None); if (!result.IsSuccess) { Trace.WriteLine($"oauth authentication failed"); return(new AuthenticationResult(AuthenticationResultType.Failure)); } // we got a toke but lets check to see the usernames match var restRootUri = new Uri(_restRootUrl); var authHeader = GetBearerHeaderAuthHeader(result.Token.Value); var userResult = await RestClient.TryGetUser(targetUri, RequestTimeout, restRootUri, authHeader); if (!userResult.IsSuccess) { Trace.WriteLine($"oauth user check failed"); return(new AuthenticationResult(AuthenticationResultType.Failure)); } if (!string.IsNullOrWhiteSpace(userResult.RemoteUsername) && !username.Equals(userResult.RemoteUsername)) { Trace.WriteLine($"Remote username [{userResult.RemoteUsername}] != [{username}] supplied username"); // make sure the 'real' username is returned return(new AuthenticationResult(AuthenticationResultType.Success, result.Token, result.RefreshToken, userResult.RemoteUsername)); } // everything is hunky dory return(result); } catch (Exception ex) { Trace.WriteLine($"oauth authentication failed [{ex.Message}]"); return(new AuthenticationResult(AuthenticationResultType.Failure)); } } else { BasicAuthAuthenticator basicauth = new BasicAuthAuthenticator(); try { var restRootUri = new Uri(_restRootUrl); return(await basicauth.GetAuthAsync(targetUri, scope, RequestTimeout, restRootUri, username, password)); } catch (Exception ex) { Trace.WriteLine($"basic auth authentication failed [{ex.Message}]"); return(new AuthenticationResult(AuthenticationResultType.Failure)); } } }
/// <inheritdoc/> public async Task <AuthenticationResult> RefreshToken(TargetUri targetUri, string refreshToken) { // Refreshing is only an OAuth concept so use the OAuth tools OAuth.OAuthAuthenticator oauth = new OAuth.OAuthAuthenticator(); try { return(await oauth.RefreshAuthAsync(targetUri, refreshToken, CancellationToken.None)); } catch (Exception ex) { Trace.WriteLine($"oauth refresh failed [{ex.Message}]"); return(new AuthenticationResult(AuthenticationResultType.Failure)); } }
/// <inheritdoc/> public async Task <AuthenticationResult> AcquireToken(TargetUri targetUri, Credential credentials, AuthenticationResultType resultType, TokenScope scope) { if (targetUri is null) { throw new ArgumentNullException(nameof(targetUri)); } if (credentials is null) { throw new ArgumentNullException(nameof(credentials)); } if (resultType < AuthenticationResultType.None || resultType > AuthenticationResultType.TwoFactor) { throw new ArgumentOutOfRangeException(nameof(resultType)); } if (scope is null) { throw new ArgumentNullException(nameof(scope)); } if (resultType == AuthenticationResultType.TwoFactor) { // A previous attempt to acquire a token failed in a way that suggests the user has // Bitbucket 2FA turned on. so attempt to run the OAuth dance... var oauth = new OAuth.OAuthAuthenticator(Context); try { var result = await oauth.GetAuthAsync(targetUri, scope, CancellationToken.None); if (!result.IsSuccess) { Trace.WriteLine($"oauth authentication failed"); return(new AuthenticationResult(AuthenticationResultType.Failure)); } // We got a toke but lets check to see the usernames match. var restRootUri = new Uri(_restRootUrl); var userResult = await(new RestClient(Context)).TryGetUser(targetUri, RequestTimeout, restRootUri, result.Token); if (!userResult.IsSuccess) { Trace.WriteLine($"oauth user check failed"); return(new AuthenticationResult(AuthenticationResultType.Failure)); } if (!string.IsNullOrWhiteSpace(userResult.RemoteUsername) && !credentials.Username.Equals(userResult.RemoteUsername)) { Trace.WriteLine($"Remote username [{userResult.RemoteUsername}] != [{credentials.Username}] supplied username"); // Make sure the 'real' username is returned. return(new AuthenticationResult(AuthenticationResultType.Success, result.Token, result.RefreshToken, userResult.RemoteUsername)); } // Everything is hunky dory. return(result); } catch (Exception ex) { Trace.WriteLine($"oauth authentication failed [{ex.Message}]"); return(new AuthenticationResult(AuthenticationResultType.Failure)); } } else { var basicauth = new BasicAuthAuthenticator(Context); try { var restRootUri = new Uri(_restRootUrl); return(await basicauth.GetAuthAsync(targetUri, scope, RequestTimeout, restRootUri, credentials)); } catch (Exception ex) { Trace.WriteLine($"basic authentication failed [{ex.Message}]"); return(new AuthenticationResult(AuthenticationResultType.Failure)); } } }
/// <inheritdoc/> public async Task <AuthenticationResult> AcquireToken(TargetUri targetUri, string username, string password, AuthenticationResultType resultType, TokenScope scope) { if (resultType == AuthenticationResultType.TwoFactor) { // a previous attempt to aquire a token failed in a way that suggests the user has // Bitbucket 2FA turned on. so attempt to run the OAuth dance... OAuth.OAuthAuthenticator oauth = new OAuth.OAuthAuthenticator(); try { return(await oauth.GetAuthAsync(targetUri, scope, CancellationToken.None)); } catch (Exception ex) { Trace.WriteLine($"oauth authentication failed [{ex.Message}]"); return(new AuthenticationResult(AuthenticationResultType.Failure)); } } else { // use the provided username and password and attempt a Basic Auth request to a known // REST API resource. Token token = null; using (HttpClientHandler handler = targetUri.HttpClientHandler) { using (HttpClient httpClient = new HttpClient(handler) { Timeout = TimeSpan.FromMilliseconds(RequestTimeout) }) { string basicAuthValue = String.Format("{0}:{1}", username, password); byte[] authBytes = Encoding.UTF8.GetBytes(basicAuthValue); basicAuthValue = Convert.ToBase64String(authBytes); httpClient.DefaultRequestHeaders.Add("Authorization", "Basic " + basicAuthValue); var url = new Uri(new Uri(_restRootUrl), UserUrl).AbsoluteUri; using (HttpResponseMessage response = await httpClient.GetAsync(url)) { Trace.WriteLine($"server responded with {response.StatusCode}."); switch (response.StatusCode) { case HttpStatusCode.OK: case HttpStatusCode.Created: { // Success with username/passord indicates 2FA is not on so // the 'token' is actually the password if we had a // successful call then the password is good. token = new Token(password, TokenType.Personal); Trace.WriteLine("authentication success: new password token created."); return(new AuthenticationResult(AuthenticationResultType.Success, token)); } case HttpStatusCode.Forbidden: { // A 403/Forbidden response indicates the username/password // are recognized and good but 2FA is on in which case we // want to indicate that with the TwoFactor result Trace.WriteLine("two-factor app authentication code required"); return(new AuthenticationResult(AuthenticationResultType.TwoFactor)); } case HttpStatusCode.Unauthorized: { // username or password are wrong. Trace.WriteLine("authentication failed"); return(new AuthenticationResult(AuthenticationResultType.Failure)); } default: // any unexpected result can be treated as a failure. Trace.WriteLine("authentication failed"); return(new AuthenticationResult(AuthenticationResultType.Failure)); } } } } } }