Skip to content

Commit ff53cd2

Browse files
committed
Issue #218 Address PR comments with minor updates
1 parent 595b632 commit ff53cd2

File tree

4 files changed

+31
-40
lines changed

4 files changed

+31
-40
lines changed

src/shared/Atlassian.Bitbucket.Tests/BitbucketHostProviderTest.cs

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ public void BitbucketHostProvider_GetCredentialAsync_Succeeds_ForFreshValidBasic
156156

157157
MockUserEntersValidBasicCredentials(bitbucketAuthentication, input, password);
158158

159-
if(BITBUCKET_DOT_ORG_HOST.Equals(host))
159+
if (BITBUCKET_DOT_ORG_HOST.Equals(host))
160160
{
161161
MockRemoteOAuthAccountIsValid(bitbucketApi, input, password, true);
162162
}
@@ -190,12 +190,6 @@ public void BitbucketHostProvider_GetCredentialAsync_Succeeds_ForFreshValid2FAAc
190190

191191
var provider = new BitbucketHostProvider(context, bitbucketAuthentication.Object, bitbucketApi.Object);
192192

193-
//if (userEntersCredentials.HasValue && !userEntersCredentials.Value)
194-
//{
195-
// Assert.ThrowsAsync<Exception>(async () => await provider.GetCredentialAsync(input));
196-
// return;
197-
//}
198-
199193
var credential = provider.GetCredentialAsync(input);
200194

201195
VerifyOAuthFlowRan(password, false, true, input, credential, null);
@@ -222,7 +216,6 @@ public void BitbucketHostProvider_GetCredentialAsync_ForcedAuthMode_IsRespected(
222216
MockUserEntersValidBasicCredentials(bitbucketAuthentication, input, password);
223217
MockRemoteBasicAuthAccountIsValidRequires2FA(bitbucketApi, input, password);
224218
bitbucketAuthentication.Setup(m => m.ShowOAuthRequiredPromptAsync()).ReturnsAsync(true);
225-
//MockRemoteValidRefreshToken();
226219

227220
var provider = new BitbucketHostProvider(context, bitbucketAuthentication.Object, bitbucketApi.Object);
228221

@@ -536,25 +529,25 @@ private void VerifyInteractiveOAuthFlowNeverRan(InputArguments input, System.Thr
536529
private void VerifyValidateBasicAuthCredentialsNeverRan()
537530
{
538531
// never check username/password works
539-
bitbucketApi.Verify(m => m.GetUserInformationAsync(It.IsAny<string>(), It.IsAny<string>(), BitbucketHostProvider.USE_BASIC_TOKEN), Times.Never);
532+
bitbucketApi.Verify(m => m.GetUserInformationAsync(It.IsAny<string>(), It.IsAny<string>(), false), Times.Never);
540533
}
541534

542535
private void VerifyValidateBasicAuthCredentialsRan()
543536
{
544537
// check username/password works
545-
bitbucketApi.Verify(m => m.GetUserInformationAsync(It.IsAny<string>(), It.IsAny<string>(), BitbucketHostProvider.USE_BASIC_TOKEN), Times.Once);
538+
bitbucketApi.Verify(m => m.GetUserInformationAsync(It.IsAny<string>(), It.IsAny<string>(), false), Times.Once);
546539
}
547540

548541
private void VerifyValidateOAuthCredentialsNeverRan()
549542
{
550543
// never check username/password works
551-
bitbucketApi.Verify(m => m.GetUserInformationAsync(null, It.IsAny<string>(), BitbucketHostProvider.USE_BASIC_TOKEN), Times.Never);
544+
bitbucketApi.Verify(m => m.GetUserInformationAsync(null, It.IsAny<string>(), false), Times.Never);
552545
}
553546

554547
private void VerifyValidateOAuthCredentialsRan()
555548
{
556549
// check username/password works
557-
bitbucketApi.Verify(m => m.GetUserInformationAsync(null, It.IsAny<string>(), BitbucketHostProvider.USE_BEARER_TOKEN), Times.Once);
550+
bitbucketApi.Verify(m => m.GetUserInformationAsync(null, It.IsAny<string>(), true), Times.Once);
558551
}
559552

560553
private void MockStoredOAuthAccount(TestCommandContext context, InputArguments input)
@@ -592,7 +585,7 @@ private static void MockRemoteBasicAuthAccountIsValid(Mock<IBitbucketRestApi> bi
592585
{
593586
var userInfo = new UserInfo() { IsTwoFactorAuthenticationEnabled = twoFAEnabled };
594587
// Basic
595-
bitbucketApi.Setup(x => x.GetUserInformationAsync(input.UserName, password, BitbucketHostProvider.USE_BASIC_TOKEN)).ReturnsAsync(new RestApiResult<UserInfo>(System.Net.HttpStatusCode.OK, userInfo));
588+
bitbucketApi.Setup(x => x.GetUserInformationAsync(input.UserName, password, false)).ReturnsAsync(new RestApiResult<UserInfo>(System.Net.HttpStatusCode.OK, userInfo));
596589

597590
}
598591

@@ -610,15 +603,15 @@ private static void MockRemoteBasicAuthAccountIsInvalid(Mock<IBitbucketRestApi>
610603
{
611604
var userInfo = new UserInfo();
612605
// Basic
613-
bitbucketApi.Setup(x => x.GetUserInformationAsync(input.UserName, password, BitbucketHostProvider.USE_BASIC_TOKEN)).ReturnsAsync(new RestApiResult<UserInfo>(System.Net.HttpStatusCode.Forbidden, userInfo));
606+
bitbucketApi.Setup(x => x.GetUserInformationAsync(input.UserName, password, false)).ReturnsAsync(new RestApiResult<UserInfo>(System.Net.HttpStatusCode.Forbidden, userInfo));
614607

615608
}
616609

617610
private static void MockRemoteOAuthAccountIsValid(Mock<IBitbucketRestApi> bitbucketApi, InputArguments input, string password, bool twoFAEnabled)
618611
{
619612
var userInfo = new UserInfo() { IsTwoFactorAuthenticationEnabled = twoFAEnabled };
620613
// OAuth
621-
bitbucketApi.Setup(x => x.GetUserInformationAsync(null, password, BitbucketHostProvider.USE_BEARER_TOKEN)).ReturnsAsync(new RestApiResult<UserInfo>(System.Net.HttpStatusCode.OK, userInfo));
614+
bitbucketApi.Setup(x => x.GetUserInformationAsync(null, password, true)).ReturnsAsync(new RestApiResult<UserInfo>(System.Net.HttpStatusCode.OK, userInfo));
622615
}
623616

624617
private static void MockStoredAccount(TestCommandContext context, InputArguments input, string password)

src/shared/Atlassian.Bitbucket.Tests/BitbucketOauth2ClientTest.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.IO;
43
using System.Net;
54
using System.Net.Http;
65
using System.Threading;
@@ -81,7 +80,6 @@ private void VerifyOAuth2TokenResult(OAuth2TokenResult result)
8180
IEnumerable<char> tokenType = null;
8281
Assert.Equal(tokenType, result.TokenType);
8382
Assert.Equal(null, result.Scopes);
84-
//Assert.Equal(pkceCodeVerifier, result.ExpiresIn);
8583
}
8684

8785
private void VerifyAuthorizationCodeResult(OAuth2AuthorizationCodeResult result)

src/shared/Atlassian.Bitbucket.Tests/BitbucketRestApiTest.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@ public async Task BitbucketRestApi_GetUserInformationAsync_ReturnsUserInfo_ForSu
3333
var httpHandler = new TestHttpMessageHandler();
3434
httpHandler.Setup(HttpMethod.Get, expectedRequestUri, request =>
3535
{
36-
if(isBearerToken)
36+
if (isBearerToken)
3737
{
3838
RestTestUtilities.AssertBearerAuth(request, password);
3939
}
4040
else
4141
{
4242
RestTestUtilities.AssertBasicAuth(request, username, password);
4343
}
44-
//AssertAuthCode(request, testAuthCode);
44+
4545
return httpResponse;
4646
});
4747
context.HttpClientFactory.MessageHandler = httpHandler;

src/shared/Atlassian.Bitbucket/BitbucketHostProvider.cs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ namespace Atlassian.Bitbucket
1010
{
1111
public class BitbucketHostProvider : IHostProvider
1212
{
13-
public const bool USE_BEARER_TOKEN = true;
14-
public const bool USE_BASIC_TOKEN = !USE_BEARER_TOKEN;
1513
private readonly ICommandContext _context;
1614
private readonly IBitbucketAuthentication _bitbucketAuth;
1715
private readonly IBitbucketRestApi _bitbucketApi;
@@ -96,7 +94,7 @@ private static void ValidateTargetUri(InputArguments input)
9694

9795
private async Task<ICredential> GetStoredCredentials(InputArguments input)
9896
{
99-
if(_context.Settings.TryGetSetting(BitbucketConstants.EnvironmentVariables.AlwaysRefreshCredentials,
97+
if (_context.Settings.TryGetSetting(BitbucketConstants.EnvironmentVariables.AlwaysRefreshCredentials,
10098
Constants.GitConfiguration.Credential.SectionName, BitbucketConstants.GitConfiguration.Credential.AlwaysRefreshCredentials,
10199
out string alwaysRefreshCredentials) && alwaysRefreshCredentials.ToBooleanyOrDefault(false))
102100
{
@@ -110,16 +108,16 @@ private async Task<ICredential> GetStoredCredentials(InputArguments input)
110108

111109
var credentials = _context.CredentialStore.Get(credentialService, input.UserName);
112110

113-
if(credentials == null)
111+
if (credentials == null)
114112
{
115113
_context.Trace.WriteLine($" Found none");
116114
return null;
117115
}
118116

119-
_context.Trace.WriteLine($" Found credentials: {credentials.Account}/**********");
117+
_context.Trace.WriteLineSecrets($" Found credentials: {credentials.Account}/{{0}}", new object[] {credentials.Password});
120118

121119
//check credentials are still valid
122-
if(!await ValidateCredentialsWork(input, credentials, GetSupportedAuthenticationModes(targetUri))) {
120+
if (!await ValidateCredentialsWork(input, credentials, GetSupportedAuthenticationModes(targetUri))) {
123121
return null;
124122
}
125123

@@ -154,7 +152,7 @@ private async Task<ICredential> GetRefreshedCredentials(InputArguments input)
154152

155153
var basicCredentials = await GetBasicCredentialsInteractive(input, authModes);
156154

157-
if(await ValidateCredentialsWork(input, basicCredentials, authModes))
155+
if (await ValidateCredentialsWork(input, basicCredentials, authModes))
158156
{
159157
return basicCredentials;
160158
}
@@ -181,8 +179,6 @@ private async Task<ICredential> GetRefreshedCredentials(InputArguments input)
181179
else
182180
{
183181
_context.Trace.WriteLine($" Found refresh token: {refreshToken} ");
184-
// TODO: should we try and compute if the AT has expired and use it?
185-
// This needs support from the credential store to record the expiry time!
186182

187183
// It's very likely that any access token expired between the last time we used/stored it.
188184
// To ensure the AT is as 'fresh' as it can be, always first try to use the refresh token
@@ -292,7 +288,7 @@ private static bool SupportsBasicAuth(AuthenticationModes authModes)
292288

293289
public AuthenticationModes GetSupportedAuthenticationModes(Uri targetUri)
294290
{
295-
if(!IsBitbucketOrg(targetUri))
291+
if (!IsBitbucketOrg(targetUri))
296292
{
297293
// Bitbucket Server/DC should use Basic only
298294
return BitbucketConstants.ServerAuthenticationModes;
@@ -361,7 +357,7 @@ public Task EraseCredentialAsync(InputArguments input)
361357

362358
private async Task<string> ResolveOAuthUserNameAsync(string accessToken)
363359
{
364-
RestApiResult<UserInfo> result = await _bitbucketApi.GetUserInformationAsync(null, accessToken, USE_BEARER_TOKEN);
360+
RestApiResult<UserInfo> result = await _bitbucketApi.GetUserInformationAsync(null, accessToken, isBearerToken: true);
365361
if (result.Succeeded)
366362
{
367363
return result.Response.UserName;
@@ -372,7 +368,7 @@ private async Task<string> ResolveOAuthUserNameAsync(string accessToken)
372368

373369
private async Task<string> ResolveBasicAuthUserNameAsync(string username, string password)
374370
{
375-
RestApiResult<UserInfo> result = await _bitbucketApi.GetUserInformationAsync(username, password, USE_BASIC_TOKEN);
371+
RestApiResult<UserInfo> result = await _bitbucketApi.GetUserInformationAsync(username, password, isBearerToken: false);
376372
if (result.Succeeded)
377373
{
378374
return result.Response.UserName;
@@ -383,15 +379,15 @@ private async Task<string> ResolveBasicAuthUserNameAsync(string username, string
383379

384380
private async Task<bool> RequiresTwoFactorAuthenticationAsync(ICredential credentials, AuthenticationModes authModes)
385381
{
386-
_context.Trace.WriteLine($"Check if 2FA si required for credentials ({credentials.Account}/**********) {authModes} ...");
382+
_context.Trace.WriteLineSecrets($"Check if 2FA si required for credentials ({credentials.Account}/{{0}}) {authModes} ...", new object[] {credentials.Password});
387383

388-
if(!SupportsOAuth(authModes))
384+
if (!SupportsOAuth(authModes))
389385
{
390386
return false;
391387
}
392388

393389
RestApiResult<UserInfo> result = await _bitbucketApi.GetUserInformationAsync(
394-
credentials.Account, credentials.Password, USE_BASIC_TOKEN);
390+
credentials.Account, credentials.Password, isBearerToken: false);
395391
switch (result.StatusCode)
396392
{
397393
// 2FA may not be required
@@ -413,26 +409,30 @@ private async Task<bool> RequiresTwoFactorAuthenticationAsync(ICredential creden
413409

414410
private async Task<bool> ValidateCredentialsWork(InputArguments input, ICredential credentials, AuthenticationModes authModes)
415411
{
416-
if(credentials == null)
412+
if (credentials == null)
417413
{
418414
return false;
419415
}
420416

417+
// TODO ideally we'd also check if the credentials have expired based on some local metadata (once/if we get such metadata storage),
418+
// and return false if they have.
419+
// This would be more efficient than having to make REST API calls to check.
420+
421421
var targetUri = input.GetRemoteUri();
422-
_context.Trace.WriteLine($"Validate credentials ({credentials.Account}/**********) are fresh for {targetUri} ...");
422+
_context.Trace.WriteLineSecrets($"Validate credentials ({credentials.Account}/{{0}}) are fresh for {targetUri} ...", new object[] {credentials.Password});
423423

424-
if(!IsBitbucketOrg(targetUri))
424+
if (!IsBitbucketOrg(targetUri))
425425
{
426426
// TODO Validate DC/Server credentials before returning them to Git
427427
// Currently credentials for DC/Server are not checked by GCM.
428-
// Instead the validation relies on Git to try and fail with the creneitals and then request GCM to erase them
428+
// Instead the validation relies on Git to try and fail with the credentials and then request GCM to erase them
429429
_context.Trace.WriteLine("For DC/Server skip validating existing credentials");
430430
return await Task.FromResult(true);
431431
}
432432

433433
// Bitbucket supports both OAuth + Basic Auth unless there is explicit GCM configuration
434434
// So the credentials could be for either scheme therefore need to potentiall test both posibilities.
435-
if(SupportsOAuth(authModes))
435+
if (SupportsOAuth(authModes))
436436
{
437437
try
438438
{
@@ -446,7 +446,7 @@ private async Task<bool> ValidateCredentialsWork(InputArguments input, ICredenti
446446
}
447447
}
448448

449-
if(SupportsBasicAuth(authModes))
449+
if (SupportsBasicAuth(authModes))
450450
{
451451
try
452452
{

0 commit comments

Comments
 (0)