Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bitbucket DC reports Must specify at least on AuthenticationModes and falls back to cli input #1460

Open
bmarroquin opened this issue Nov 3, 2023 · 7 comments
Labels
auth-issue An issue authenticating to a host bug A bug in Git Credential Manager host:bitbucket Specific to the Bitbucket host provider

Comments

@bmarroquin
Copy link

bmarroquin commented Nov 3, 2023

Version

2.3.2

Operating system

Windows

OS version or distribution

Windows 10 x64

Git hosting provider(s)

Bitbucket Server/DC

Other hosting provider

No response

(Azure DevOps only) What format is your remote URL?

None

Can you access the remote repository directly in the browser?

Yes, I can access the repository

Expected behavior

I expected the UI to pop up and prompt me for my username + token

Actual behavior

A fatal message is displayed Must specify at least one AuthenticationModes and then a CLI prompt asks for username and password.

Logs

The issue is that BitbucketHelper.GetBaseUri doesn't consider that Bitbucket DC could be proxied behind a path. For example, https://<host>/bitbucket. The method drops the needed path and causes 404 errors in the following API requests.
Then DataCenter.BitbucketRestApi.GetAuthenticationMethodsAsync and DataCenter.BitbucketRestApi.IsOAthInstalledAsync swallow the 404 errors and 0 Authentication modes are returned.

A quick fix would be to have DataCenter.BitbucketRestApi.GetAuthenticationMethodsAsync raise an exception on a 404 and the fallback logic in
BitbucketHostProvider.GetSupportedAuthenticationsModesAsync should kick in and i would expect everything to work.

git clone <host>/bitbucket/scm/<projectkey>/<repo>.git sfsf
Cloning into 'sfsf'...
16:39:04.620409 ...\Application.cs:95   trace: [RunInternalAsync] Version: 2.0.935.18315
16:39:04.636742 ...\Application.cs:96   trace: [RunInternalAsync] Runtime: .NET Framework 4.0.30319.42000
16:39:04.636742 ...\Application.cs:97   trace: [RunInternalAsync] Platform: Windows (x86-64)
16:39:04.636742 ...\Application.cs:98   trace: [RunInternalAsync] OSVersion: 10.0 (build 19045)
16:39:04.636742 ...\Application.cs:99   trace: [RunInternalAsync] AppPath: C:\Program Files\Git\mingw64\bin\git-credential-manager
16:39:04.636742 ...\Application.cs:100  trace: [RunInternalAsync] InstallDir: C:\Program Files\Git\mingw64\bin\
16:39:04.636742 ...\Application.cs:101  trace: [RunInternalAsync] Arguments: get
16:39:04.666881 ...GitCommandBase.cs:33 trace: [ExecuteAsync] Start 'get' command...
16:39:04.676790 ...GitCommandBase.cs:47 trace: [ExecuteAsync] Detecting host provider for input:
16:39:04.676790 ...GitCommandBase.cs:48 trace: [ExecuteAsync]   protocol=https
16:39:04.676790 ...GitCommandBase.cs:48 trace: [ExecuteAsync]   host=<host>
16:39:04.716857 ...oviderRegistry.cs:99 trace: [GetProviderAsync] Host provider override was set id='bitbucket'
16:39:04.726785 ...GitCommandBase.cs:50 trace: [ExecuteAsync] Host provider 'Bitbucket' was selected.
16:39:04.811054 ...tHostProvider.cs:277 trace: [GetSupportedAuthenticationModesAsync] <host>/ is Bitbucket DC - checking for supported authentication schemes...
16:39:04.821049 ...bucketRestApi.cs:100 trace: [GetAuthenticationMethodsAsync] HTTP: GET <host>/rest/authconfig/1.0/login-options
16:39:04.821049 ...pClientFactory.cs:58 trace: [CreateClient] Creating new HTTP client instance...
16:39:05.441305 ...pClientFactory.cs:97 trace: [CreateClient] Custom certificate verification has been enabled with certificate bundle at C:/Program Files/Git/mingw64/etc/ssl/certs/ca-bundle.crt
16:39:05.821410 ...bucketRestApi.cs:103 trace: [GetAuthenticationMethodsAsync] HTTP: Response 404 [NotFound]
16:39:05.821410 ...tbucketRestApi.cs:77 trace: [IsOAuthInstalledAsync] HTTP: GET <host>/rest/oauth2/1.0/client
16:39:06.071414 ...tbucketRestApi.cs:80 trace: [IsOAuthInstalledAsync] HTTP: Response 404 [NotFound]
16:39:06.071414 ...tHostProvider.cs:296 trace: [GetSupportedAuthenticationModesAsync] Bitbucket DC/Server instance supports authentication schemes: None
16:39:06.191234 ...tHostProvider.cs:103 trace: [GetStoredCredentials] Look for existing credentials under <host> ...
16:39:06.370031 ...tHostProvider.cs:109 trace: [GetStoredCredentials] No stored credentials found
16:39:06.370031 ...tHostProvider.cs:126 trace: [GetRefreshedCredentials] Refresh credentials...
16:39:06.370031 ...tHostProvider.cs:132 trace: [GetRefreshedCredentials] Checking for refresh token...
16:39:06.370031 ...tHostProvider.cs:139 trace: [GetRefreshedCredentials] No stored refresh token found
16:39:06.370031 ...tHostProvider.cs:143 trace: [GetRefreshedCredentials] Prompt for credentials...
fatal: Must specify at least one AuthenticationModes
Parameter name: modes
   at Atlassian.Bitbucket.BitbucketAuthentication.<GetCredentialsAsync>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Atlassian.Bitbucket.BitbucketHostProvider.<GetRefreshedCredentials>d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Atlassian.Bitbucket.BitbucketHostProvider.<GetCredentialAsync>d__13.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at GitCredentialManager.Commands.GetCommand.<ExecuteInternalAsync>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at GitCredentialManager.Commands.GitCommandBase.<ExecuteAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.CommandLine.Invocation.CommandHandler.<GetExitCodeAsync>d__70.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.CommandLine.Invocation.ModelBindingCommandHandler.<InvokeAsync>d__12.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.CommandLine.Invocation.InvocationPipeline.<>c__DisplayClass4_0.<<BuildInvocationChain>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass23_0.<<UseParseErrorReporting>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass16_0.<<UseHelp>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass27_0.<<UseVersionOption>b__1>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass25_0.<<UseTypoCorrections>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<UseSuggestDirective>b__24_0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass22_0.<<UseParseDirective>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass11_0.<<UseDebugDirective>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<RegisterWithDotnetSuggest>b__10_0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass14_0.<<UseExceptionHandler>b__0>d.MoveNext()
Username for '<host>':
@bmarroquin bmarroquin added the auth-issue An issue authenticating to a host label Nov 3, 2023
@bmarroquin bmarroquin changed the title Bitbucket DC reports Must scpecify at least on AuthenticationModes and fallsback to cli input Bitbucket DC reports Must specify at least on AuthenticationModes and falls back to cli input Nov 3, 2023
@mjcheetham mjcheetham added bug A bug in Git Credential Manager host:bitbucket Specific to the Bitbucket host provider labels Nov 3, 2023
@mjcheetham
Copy link
Collaborator

Thanks for raising this issue!

As a workaround until this is fixed, could you try manually setting the authentication modes in Git config?

git config --global credential.https://<host>.bitbucketAuthModes "oauth,basic"

where <host> is the hostname of the DC instance.

https://gh.io/gcm/config#credentialbitbucketauthmodes

@bmarroquin
Copy link
Author

bmarroquin commented Nov 8, 2023

Yeah, the workaround works. Thanks.

Update: This works but is inconsistent, look at last comment for more reliable workaround.

@heydayton
Copy link

Just had the same issue. I recently had to update my bitbucket password and I could not get the new credentials to stick. Running the above credential config command resolved this. The next time I pushed, Atlassian presented a user/password dialog.

@bmarroquin
Copy link
Author

I finally got time to dig into this more. Setting the authModes works but it prompts for credentials every time. This happens because it tries to validate the credentials against the path less URL. See log below.

17:37:44.356528 ...tHostProvider.cs:113 trace: [GetStoredCredentials] Found stored credentials: <user>/********
17:37:44.451164 ...tHostProvider.cs:393 trace: [ValidateCredentialsWork] Validate credentials (<user>/********) are fresh for https://<host>/ ...
17:37:44.548164 ...tbucketRestApi.cs:52 trace: [GetUserInformationAsync] HTTP: GET https://<host>/rest/api/1.0/users
17:37:44.549165 ...pClientFactory.cs:58 trace: [CreateClient] Creating new HTTP client instance...
17:37:45.550022 ...tbucketRestApi.cs:55 trace: [GetUserInformationAsync] HTTP: Response 404 [NotFound]
17:37:45.551024 ...tHostProvider.cs:422 trace: [ValidateCredentialsWork] Failed to validate existing credentials using Basic Auth
17:37:45.551024 ...tHostProvider.cs:423 trace: [ValidateCredentialsWork] ! error: 'Failed to resolve username. HTTP: NotFound'.

Adding usehttppath for the host works a little better and I no longer have to provide the credentials again, but only for a specific repository. The credentials are stored with the whole path https://<host>/bitbucket/scm/project/repo.git. This causes me to re-authenticate for every repository on this server. If we could change the Get/SetStoredCredential method to use BitbucketHelper.GetBaseUri i think that would normalize and prevent re-entering auth for all repositories.

Alternatively, i tried to use only usehttppath, but that never makes it to the UI as it fails with fatal: Bitbucket DC OAuth Client ID must be defined because it tries to force the use of OAuth.

GCM makes the assumption that just because rest/authconfig/1.0/login-options doesn't list basic authentication, it isn't available. Basic Authentication can be enabled for API calls and that rest endpoint won't show it as an option. That could arguably be a Bitbucket DC bug, but it could also be a misuse of that endpoint since it might be only for the UI login options. GCM also makes the assumption that just because the OAuth endpoints are available, that the OAuth workflow is an option.

Ultimately, i think the solution should involve the following:

  1. Always include basic authentication as option. It is currently not possible to determine if it is enabled or disabled reliably with or without usehttppath.
  2. If Bitbucket DC supports OAuth and Bitbucket DC OAuth Client ID is defined, add OAuth as an option and maybe use it by default.

roodymoody1 referenced this issue Apr 13, 2024
Remove ESRP-related scripts, as we are no longer using this tool for signing.
@bmarroquin
Copy link
Author

bmarroquin commented Apr 15, 2024

After some more digging I found more inconsistent behavior, if i set the credentials directly in WinCred, set the provider as bitbucket and run the tool, i expect ResolveBasicAuthUserNameAsync to fail due to a 404 or 401, but it was still working. Since we currently cannot determine AuthModes, it should not be possible to verify the credentials. It turns out that ValidateCredentialsWork will always return true if no AuthModes are detected. Whatever fix is deployed, should also keep this in mind.

@bmarroquin
Copy link
Author

bmarroquin commented Apr 15, 2024

The best workaround right now is to use the generic provider for this.
git config --global credential.https://<host>.provider "generic"

@roodymoody1

This comment was marked as outdated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auth-issue An issue authenticating to a host bug A bug in Git Credential Manager host:bitbucket Specific to the Bitbucket host provider
Projects
None yet
Development

No branches or pull requests

4 participants