git-ecosystem / git-credential-manager

Secure, cross-platform Git credential storage with authentication to GitHub, Azure Repos, and other popular Git hosting services.
Other
6.75k stars 1.76k forks source link

Authentication to on-prem Bitbucket Datacenter with SSO enabled times out #326

Closed ibauersachs closed 1 year ago

ibauersachs commented 3 years ago

Which version of GCM Core are you using?

2.0.394-beta+3fc6791abf (via Git 2.31.1.windows.1)

(note that 2.0.318-beta+44acfafa98 from a co-worker's Git 2.30.1.windows.1 still works)

Which Git host provider are you trying to connect to?

Bitbucket Datacenter (on-prem) with OIDC SSO enabled. Thus the dashboard redirects to our ADFS server. Git authentication should happen with HTTP Basic or a PAT. There is AFAIK no OIDC authentication on the Bitbucket Datacenter REST API and Git endpoints.

Can you access the remote repository directly in the browser using the remote URL?


[Azure DevOps only] What format is your remote URL?

[Azure DevOps only] If the account picker shows more than one identity as you authenticate, check that you selected the same one that has access on the web.


Expected behavior

I am authenticated and my Git operation completes successfully.

Actual behavior

gcm hangs while trying to auto-detect the server product.

Logs

14:18:00.192091 ...\Application.cs:84   trace: [RunInternalAsync] Version: 2.0.394.50751
14:18:00.197186 ...\Application.cs:85   trace: [RunInternalAsync] Runtime: .NET Framework 4.0.30319.42000
14:18:00.197186 ...\Application.cs:86   trace: [RunInternalAsync] Platform: Windows (x86-64)
14:18:00.197186 ...\Application.cs:87   trace: [RunInternalAsync] AppPath: git-credential-manager-core
14:18:00.197186 ...\Application.cs:88   trace: [RunInternalAsync] Arguments: get
14:18:00.244997 ...GitCommandBase.cs:35 trace: [ExecuteAsync] Start 'get' command...
14:18:00.251989 ...GitCommandBase.cs:49 trace: [ExecuteAsync] Detecting host provider for input:
14:18:00.253334 ...GitCommandBase.cs:50 trace: [ExecuteAsync]   protocol=http
14:18:00.253334 ...GitCommandBase.cs:50 trace: [ExecuteAsync]   host=<bitbucket-sever-host>
14:18:00.353151 ...viderRegistry.cs:149 trace: [GetProviderAsync] Performing auto-detection of host provider.
14:18:00.354150 ...viderRegistry.cs:162 trace: [GetProviderAsync] Checking against 3 host providers registered with priority 'Normal'.
14:18:00.356184 ...viderRegistry.cs:154 trace: [GetProviderAsync] Querying remote URL for host provider auto-detection.
14:18:00.357186 ...pClientFactory.cs:54 trace: [CreateClient] Creating new HTTP client instance...

Looking on the server, the following URLs are HEAD-ed:

[15/Apr/2021:14:18:00 +0200] "HEAD / HTTP/1.1" 302 226 "-" "Git-Credential-Manager/2.0.394.50751 (Windows; x86-64) CLR/.NET Framework 4.0.30319.42000"
[15/Apr/2021:14:18:00 +0200] "HEAD / HTTP/1.1" 302 6228 "-" "Git-Credential-Manager/2.0.394.50751 (Windows; x86-64) CLR/.NET Framework 4.0.30319.42000"
[15/Apr/2021:14:18:00 +0200] "HEAD /dashboard HTTP/1.1" 302 469 "-" "Git-Credential-Manager/2.0.394.50751 (Windows; x86-64) CLR/.NET Framework 4.0.30319.42000"
[15/Apr/2021:14:18:00 +0200] "HEAD /login?nextUrl=%2Fdashboard HTTP/1.1" 302 620 "-" "Git-Credential-Manager/2.0.394.50751 (Windows; x86-64) CLR/.NET Framework 4.0.30319.42000"

Manually getting these URLs gives back:

curl -I https://<bitbucket-sever-host>
HTTP/1.1 302
Date: Thu, 15 Apr 2021 12:18:55 GMT
Server: Apache/2.4.18 (Ubuntu)
X-AREQUESTID: @1NGZ2ROx858x9369539x0
x-xss-protection: 1; mode=block
x-frame-options: SAMEORIGIN
x-content-type-options: nosniff
Pragma: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Cache-Control: no-cache
Cache-Control: no-store
Location: https://<bitbucket-sever-host>/dashboard
Content-Language: en-US
Transfer-Encoding: chunked

->

curl -I https://<bitbucket-sever-host>/dashboard
HTTP/1.1 302
Date: Thu, 15 Apr 2021 12:21:13 GMT
Server: Apache/2.4.18 (Ubuntu)
X-AREQUESTID: @1NGZ2ROx861x9370409x0
x-xss-protection: 1; mode=block
x-frame-options: SAMEORIGIN
x-content-type-options: nosniff
Pragma: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Cache-Control: no-cache
Cache-Control: no-store
Location: https://<bitbucket-sever-host>/login?nextUrl=%2Fdashboard
Content-Language: en-US
Transfer-Encoding: chunked

->

curl -I https://<bitbucket-sever-host>/login?nextUrl=%2Fdashboard
HTTP/1.1 302
Date: Thu, 15 Apr 2021 12:21:40 GMT
Server: Apache/2.4.18 (Ubuntu)
X-AREQUESTID: @1NGZ2ROx861x9370425x0
Location: https://<onprem-adfs-server>/adfs/oauth2/authorize/?scope=openid&response_type=code&redirect_uri=https%3A%2F%2F<bitbucket-sever-host>%2Fplugins%2Fservlet%2Foidc%2Fcallback&state=9HRpnhi1ExGki7Qa8YiFFVwDFamT90NDkrbzk9dt7mY&nonce=dGUsg_faaYlu5duLxKoVXArydWvbRZc4Zzo09KsTVmI&client_id=e714add8-5514-4aeb-8750-339520655a6b
Transfer-Encoding: chunked
Set-Cookie: session-data-9HRpnhi1ExGki7Qa8YiFFVwDFamT90NDkrbzk9dt7mY=; Path=/; Max-Age=300; Secure; HttpOnly; SameSite=None

I don't know if gcm also follows the redirects to ADFS and what happens there, but this is already a long list of redirects that won't lead to any result.

Workaround (both settings are required):

[credential "<bitbucket-sever-host>"]
    provider = generic
    allowWindowsAuth = false
Chft1234 commented 1 year ago

قهنقنق

ldennington commented 1 year ago

Closing, as Bitbucket DC now supports OAuth and you can forcibly specify use of OAuth for a particular remote. See this comment for more details.

ibauersachs commented 1 year ago

@ldennington The issue you linked is for Bitbucket Cloud, while my issue here is about Bitbucket Server (or DC).

Also:

Please reopen this issue.

tdillon commented 1 year ago

Please reopen this issue.

I'm guessing this won't be reopened.

We're also using Bitbucket Data Center with OpenID Connect. We authenticate using PIV/CAC not username/password.

ldennington commented 1 year ago

@tdillon - thanks for elevating the above request. Apologies we didn't do this sooner.

@mminns - given that @mjcheetham and I don't have a DC instance, would you be willing to confirm that GCM hangs in auto-detection on your instance and, if so, help us validate the fix once it's in place?

mminns commented 1 year ago

Morning, yes I can have a look.

ibauersachs commented 1 year ago

There's no need for a regular Bitbucket DC installation, Atlassian's SDK with the atlas-run-standalone --product bitbucket command can start instances for such purposes. See here: https://developer.atlassian.com/server/framework/atlassian-sdk/atlas-run-standalone/

mminns commented 1 year ago

@ibauersachs is correct about using atlas-run-standalone

I am interested by this issue because I successfully use Oauth with our in-house Bitbucket DC instances daily.

Bitbucket DC does support OAuth 2.0.

It is correct that an Admin must set up the server and generate the consumer key and secret but once done. Local installs of GCM can be configured with the key and secret and then use the 3LO flow to authenticate individual users.

tdillon commented 1 year ago

@ibauersachs I followed the instructions on Bitbucket Authentication, 2FA and OAuth and came up with the following .gitconfig.

[credential "https://my.bitbucket.server.gov/bitbucket"]
    provider = bitbucket
    bitbucketDataCenterOAuthClientId = 11111111111111111111111111111111
    bitbucketDataCenterOAuthClientSecret = 2222222222222222222222222222222222222222222222222222222222222222
    usehttppath = true

With this .gitconfig git is able to start the oauth authentication flow. I'm able to authenticate with my IDP and I get redirected to Bitbucket's "oauth consent" page. On that page there are Allow and Deny buttons.

Unfortunately for me, when I click Allow I am just redirected back to the same page. I have a support ticket with Atlassian to help track down the issue. I'm curious if you'd have better luck with a similar setup. I am also curious if having the client id and secret in plain text on each developer's machine is an issue, but for now I'm just trying to get it working.

mminns commented 1 year ago

That matches my config which is working.

❯ git config --global -l
...
credential.https://my-bitbucket-server.atlassian.com.provider=bitbucket
credential.https://my-bitbucket-server.atlassian.com.bitbucketdatacenteroauthclientid=11111111111111111111111111111111111111
credential.https://my-bitbucket-server.atlassian.com.bitbucketdatacenteroauthclientsecret=2222222222222222222222222222222222222222222222222222222222222
...

The redirect after Allow sounds like something happening in your server/network side rather than from GCM.

Have you tried using the env var GCM_TRACE = 1 to see the flow of requests from GCM to see if there is communication after the Allow ?

mminns commented 1 year ago

Re: The client ID and secret being in plaintext.

To be fair it is something I have wondered about from time to time.

In principal it would be possible to obscure them on disk, or perhaps store them somewhere like the Vault, but at somepoint they need to be distributed to users and it seems to me that either has to be in plaintext, to be encoded locally, or in encoded form, but then the client application needs to be able to decode them for use. As an open source dotnet application it would be easy for someone to reverse engineer that decoding process if they have access to the encoded values.

So I'm not sure you actually gain much ... but I'm not a security expert.

Ultimately you are relying on the security of the client workstation, AFAICS

tdillon commented 1 year ago

Have you tried using the env var GCM_TRACE = 1 to see the flow of requests from GCM to see if there is communication after the Allow ?

I have. The git client does not receive any communication after clicking Allow. I agree the issue is with our server or network.

Ultimately you are relying on the security of the client workstation, AFAICS

I'll have to ask Atlassian support for their take and the risks with this setup.

ldennington commented 1 year ago

@ibauersachs - are you able to test out the config highlighted by @tdillon and @mminns to see if it works for you?

ibauersachs commented 1 year ago

Sorry, I've been rather busy. I can try the config, but configuring anything manually is beside the point of this issue: we have basic auth enabled (along with SSO) and a git clone https://bitbucket.example.org/scm/project/repo.git makes GCM hang (as long as there is no additional config) and without any user feedback whatsoever. This should not happen.

ldennington commented 1 year ago

From your logs, it seems like we are either hanging following a redirect to an ADFS instance or are stuck in a redirect loop. We cannot tell this for sure from the logs. However, we could consider disabling redirects during host provider discovery HEAD requests as a possible mitigation. This could prevent us from correctly discovering hosts, though. Do you know if a redirect loop is happening from the logs on your side? Sadly, the .NET HttpClient doesn't provide insight into redirects; all we can do is disable or set an arbitrary limit.

ibauersachs commented 1 year ago

Sorry for the late reply. I finally found some time to investigate again and wanted to compile if necessary. Things seem to have changed in the meantime. With Git 2.41.0.windows.1 and gcm 2.1.2 the hang doesn't happen anymore. The output without any specific host configuration and without saved credentials is now

git clone https://git.example.com/scm/~ibauersachs/gcm-test.git
Cloning into 'gcm-test'...
fatal: Bitbucket DC OAuth Client ID must be defined
Username for 'https://git.example.com': ibauersachs
Password for 'https://ibauersachs@git.example.com':

When entering the correct credentials, the password is saved and .gitconfig is changed to

[credential "https://git.example.com"]
    provider = bitbucket

So I guess this can actually be closed.

ldennington commented 1 year ago

@ibauersachs - thanks for the followup. Going to go ahead and close accordingly.