Encode redirect URL if needed on oauth callback request (#654)

Some SCM providers like BItBucket Server decode the callback url so that cause IllegalArgumentException error. Catch the error and decode the redirect url.
pull/656/head
Igor Vinokur 2024-02-19 19:07:07 +02:00 committed by GitHub
parent 4f8a84cb1d
commit f9f4c8e5d5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 60 additions and 7 deletions

View File

@ -96,7 +96,9 @@ public class EmbeddedOAuthAPI implements OAuthAPI {
if (!isNullOrEmpty(redirectAfterLogin)
&& errorValues != null
&& errorValues.contains("access_denied")) {
return Response.temporaryRedirect(URI.create(encodeRedirectUrl())).build();
return Response.temporaryRedirect(
URI.create(encodeRedirectUrl(redirectAfterLogin + "&error_code=access_denied")))
.build();
}
final String providerName = getParameter(params, "oauth_provider");
OAuthAuthenticator oauth = getAuthenticator(providerName);
@ -123,7 +125,14 @@ public class EmbeddedOAuthAPI implements OAuthAPI {
LOG.error(e.getMessage(), e);
}
final String redirectAfterLogin = getParameter(params, "redirect_after_login");
return Response.temporaryRedirect(URI.create(redirectAfterLogin)).build();
URI uri;
try {
uri = URI.create(redirectAfterLogin);
} catch (IllegalArgumentException e) {
// the redirectUrl was decoded by the CSM provider, so we need to encode it back.
uri = URI.create(encodeRedirectUrl(redirectAfterLogin));
}
return Response.temporaryRedirect(uri).build();
}
/**
@ -131,12 +140,10 @@ public class EmbeddedOAuthAPI implements OAuthAPI {
* JSON, as a query parameter. This prevents passing unsupported characters, like '{' and '}' to
* the {@link URI#create(String)} method.
*/
private String encodeRedirectUrl() {
private String encodeRedirectUrl(String url) {
try {
URL url = new URL(redirectAfterLogin);
String query = url.getQuery();
return redirectAfterLogin.substring(0, redirectAfterLogin.indexOf(query))
+ URLEncoder.encode(query + "&error_code=access_denied", UTF_8);
String query = new URL(url).getQuery();
return url.substring(0, url.indexOf(query)) + URLEncoder.encode(query, UTF_8);
} catch (MalformedURLException e) {
LOG.error(e.getMessage(), e);
throw new RuntimeException(e);

View File

@ -11,6 +11,8 @@
*/
package org.eclipse.che.security.oauth;
import static java.net.URLEncoder.encode;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.eclipse.che.api.factory.server.scm.PersonalAccessTokenFetcher.OAUTH_2_PREFIX;
@ -140,4 +142,48 @@ public class EmbeddedOAuthAPITest {
assertTrue(token.getScmTokenName().startsWith(OAUTH_2_PREFIX));
assertEquals(token.getToken(), "token");
}
@Test
public void shouldEncodeRedirectUrl() throws Exception {
// given
UriInfo uriInfo = mock(UriInfo.class);
OAuthAuthenticator authenticator = mock(OAuthAuthenticator.class);
when(uriInfo.getRequestUri())
.thenReturn(
new URI(
"http://eclipse.che?state=oauth_provider"
+ encode(
"=github&redirect_after_login=https://redirecturl.com?params="
+ encode("{}", UTF_8),
UTF_8)));
when(oauth2Providers.getAuthenticator("github")).thenReturn(authenticator);
// when
Response callback = embeddedOAuthAPI.callback(uriInfo, emptyList());
// then
assertEquals(callback.getLocation().toString(), "https://redirecturl.com?params%3D%7B%7D");
}
@Test
public void shouldNotEncodeRedirectUrl() throws Exception {
// given
UriInfo uriInfo = mock(UriInfo.class);
OAuthAuthenticator authenticator = mock(OAuthAuthenticator.class);
when(uriInfo.getRequestUri())
.thenReturn(
new URI(
"http://eclipse.che?state=oauth_provider"
+ encode(
"=github&redirect_after_login=https://redirecturl.com?params="
+ encode(encode("{}", UTF_8), UTF_8),
UTF_8)));
when(oauth2Providers.getAuthenticator("github")).thenReturn(authenticator);
// when
Response callback = embeddedOAuthAPI.callback(uriInfo, emptyList());
// then
assertEquals(callback.getLocation().toString(), "https://redirecturl.com?params=%7B%7D");
}
}