Skip to content

Commit 50f29ad

Browse files
authored
Additionaly encode Bitbucket Server authentication url state (#808)
Encode the Bitbucket Server authentication url twice, because Bitbucket Server Decodes the callback url request.
1 parent 744041e commit 50f29ad

File tree

2 files changed

+81
-2
lines changed

2 files changed

+81
-2
lines changed

wsmaster/che-core-api-auth-bitbucket/src/main/java/org/eclipse/che/security/oauth/BitbucketOAuthAuthenticator.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012-2024 Red Hat, Inc.
2+
* Copyright (c) 2012-2025 Red Hat, Inc.
33
* This program and the accompanying materials are made
44
* available under the terms of the Eclipse Public License 2.0
55
* which is available at https://www.eclipse.org/legal/epl-2.0/
@@ -12,6 +12,7 @@
1212
package org.eclipse.che.security.oauth;
1313

1414
import static com.google.common.base.Strings.isNullOrEmpty;
15+
import static java.net.URLEncoder.encode;
1516
import static java.nio.charset.StandardCharsets.UTF_8;
1617

1718
import com.google.api.client.auth.oauth2.AuthorizationCodeRequestUrl;
@@ -49,7 +50,10 @@ public BitbucketOAuthAuthenticator(
4950
@Override
5051
public String getAuthenticateUrl(URL requestUrl, List<String> scopes) {
5152
AuthorizationCodeRequestUrl url = flow.newAuthorizationUrl().setScopes(scopes);
52-
url.setState(prepareState(requestUrl));
53+
String state = prepareState(requestUrl);
54+
// Although the state is encoded in the OAuthAuthenticator class, we need to additionally encode
55+
// it because Bitbucket Server decodes it on callback request.
56+
url.setState(BITBUCKET_CLOUD_ENDPOINT.equals(bitbucketEndpoint) ? state : encode(state, UTF_8));
5357
url.set("redirect_uri", findRedirectUrl(requestUrl));
5458
return url.build();
5559
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright (c) 2012-2025 Red Hat, Inc.
3+
* This program and the accompanying materials are made
4+
* available under the terms of the Eclipse Public License 2.0
5+
* which is available at https://www.eclipse.org/legal/epl-2.0/
6+
*
7+
* SPDX-License-Identifier: EPL-2.0
8+
*
9+
* Contributors:
10+
* Red Hat, Inc. - initial API and implementation
11+
*/
12+
package org.eclipse.che.security;
13+
14+
import static java.util.Collections.emptyList;
15+
import static org.testng.Assert.assertTrue;
16+
17+
import com.google.common.io.Files;
18+
import java.io.File;
19+
import java.io.IOException;
20+
import java.net.URL;
21+
import java.nio.charset.Charset;
22+
import org.eclipse.che.security.oauth.BitbucketOAuthAuthenticatorProvider;
23+
import org.eclipse.che.security.oauth.OAuthAuthenticator;
24+
import org.testng.annotations.BeforeClass;
25+
import org.testng.annotations.Test;
26+
27+
public class BitbucketOAuthAuthenticatorProviderTest {
28+
private BitbucketOAuthAuthenticatorProvider provider;
29+
private File cfgFile;
30+
31+
@BeforeClass
32+
public void setup() throws IOException {
33+
cfgFile = File.createTempFile("BitbucketOAuthAuthenticatorProviderTest-", "-cfg");
34+
Files.asCharSink(cfgFile, Charset.defaultCharset()).write("tmp-data");
35+
cfgFile.deleteOnExit();
36+
provider =
37+
new BitbucketOAuthAuthenticatorProvider(
38+
"http://bitubucket-server.com",
39+
cfgFile.getPath(),
40+
cfgFile.getPath(),
41+
new String[] {"http://che.server.com"},
42+
"http://auth.uri",
43+
"http://token.uri");
44+
}
45+
46+
@Test
47+
public void shouldReturnAuthenticationUrlEncodedOnce() throws Exception {
48+
// given
49+
BitbucketOAuthAuthenticatorProvider provider =
50+
new BitbucketOAuthAuthenticatorProvider(
51+
"https://bitbucket.org",
52+
cfgFile.getPath(),
53+
cfgFile.getPath(),
54+
new String[] {"http://che.server.com"},
55+
"http://auth.uri",
56+
"http://token.uri");
57+
OAuthAuthenticator authenticator = provider.get();
58+
URL url = new URL("http://che.server.com?query=param");
59+
// when
60+
String authenticateUrl = authenticator.getAuthenticateUrl(url, emptyList());
61+
// then
62+
assertTrue(authenticateUrl.endsWith("&state=query%253Dparam"));
63+
}
64+
65+
@Test
66+
public void shouldReturnAuthenticationUrlEncodedTwice() throws Exception {
67+
// given
68+
OAuthAuthenticator authenticator = provider.get();
69+
URL url = new URL("http://che.server.com?query=param");
70+
// when
71+
String authenticateUrl = authenticator.getAuthenticateUrl(url, emptyList());
72+
// then
73+
assertTrue(authenticateUrl.endsWith("&state=query%25253Dparam"));
74+
}
75+
}

0 commit comments

Comments
 (0)