-
Type:
Bug
-
Resolution: Fixed
-
Priority:
Major
-
Component/s: bitbucket-branch-source-plugin
-
Environment:- Bitbucket Cloud (bitbucket.org)
- cloudbees-bitbucket-branch-source: 937.3.1
- Credential: "Username with password", username = OAuth consumer key, password = OAuth consumer secret (per the plugin USER_GUIDE OAuth instructions)
-
937.3.3
Reproduction steps
- In Bitbucket Cloud, create an OAuth consumer (Workspace settings > OAuth consumers), check "This is a private consumer", grant Account read, Repositories read/write, Pull requests read, Webhooks read+write. Note that Bitbucket generates a 32-character key and a longer secret (e.g. 76 chars).
- In Jenkins, add a "Username with password" credential: username = consumer key, password = consumer secret. Reference it from a Bitbucket org folder / BitbucketSCMNavigator.
- Trigger an organization scan.
- Confirm the consumer itself is valid by performing the same client_credentials exchange the plugin would do, then calling the REST API with the resulting bearer token
- Token exchange (Basic auth of key:secret against the token endpoint) -> HTTP 200, returns a Bearer access_token
curl -s -X POST -u "<KEY>:<SECRET>" -d grant_type=client_credentials https://bitbucket.org/site/oauth2/access_token - API call using the Bearer token -> HTTP 200
curl -s -H "Authorization: Bearer <ACCESS_TOKEN>" https://api.bitbucket.org/2.0/repositories/<WORKSPACE>?pagelen=1 - What the plugin actually does instead (Basic auth of key:secret against the API) -> HTTP 401 Unauthorized
curl -s -u "<KEY>:<SECRET>" https://api.bitbucket.org/2.0/repositories/<WORKSPACE>?pagelen=1
- Token exchange (Basic auth of key:secret against the token endpoint) -> HTTP 200, returns a Bearer access_token
Expected Results
The plugin recognizes the username/password credential as an OAuth consumer regardless of the exact key/secret lengths Bitbucket issues, performs the client_credentials token exchange, and authenticates API requests with the resulting Bearer token. The organization scan succeeds.
Actual Results
The organization scan fails. Because the key is 32 chars (not 18) and the secret is longer than 32, BitbucketOAuthCredentialMatcher returns false, the OAuth authenticator is not selected, and the plugin uses HTTP Basic Auth with the consumer key:secret. Bitbucket rejects this with HTTP 401, surfaced as:
Connecting to https://bitbucket.org using <KEY>/****** (Bitbucket OAuth client key and secret)
ERROR: Could not fetch sources from navigator ...BitbucketSCMNavigator@...
FATAL: Failed to recompute children of Bitbucket
com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketRequestException: HTTP request error.
Status: Unauthorized HTTP 401
Why?
cloudbees-bitbucket-branch-source v937.3.1 decides whether a username/password credential is an OAuth consumer using a hardcoded length heuristic in BitbucketOAuthCredentialMatcher:
- consumer key (username) length == 18
- consumer secret (password) length == 32
Bitbucket Cloud now generates longer OAuth keys (32-char) and secret (76-char), but the plugin still only recognizes the legacy 18/32 format. Both fail the check, so the plugin never selects the OAuth authenticator and falls through to Basic Auth with key:secret leading to HTTP 401 error.
Suggested fix
Stop gating OAuth detection on exact legacy lengths. Either relax BitbucketOAuthCredentialMatcher (for example, accept keys/secrets within a length range and/or attempt the client_credentials exchange to detect OAuth consumers), or expose an explicit "OAuth consumer" credential type / a checkbox so the authenticator selection does not depend on a length heuristic that no longer matches Bitbucket-issued credentials.
Â
- links to