diff --git a/wsmaster/che-core-api-factory-azure-devops/src/main/java/org/eclipse/che/api/factory/server/azure/devops/AzureDevOpsApiClient.java b/wsmaster/che-core-api-factory-azure-devops/src/main/java/org/eclipse/che/api/factory/server/azure/devops/AzureDevOpsApiClient.java
index 87616776a7..ec7633216d 100644
--- a/wsmaster/che-core-api-factory-azure-devops/src/main/java/org/eclipse/che/api/factory/server/azure/devops/AzureDevOpsApiClient.java
+++ b/wsmaster/che-core-api-factory-azure-devops/src/main/java/org/eclipse/che/api/factory/server/azure/devops/AzureDevOpsApiClient.java
@@ -12,9 +12,12 @@
package org.eclipse.che.api.factory.server.azure.devops;
import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
+import static java.net.HttpURLConnection.HTTP_FORBIDDEN;
+import static java.net.HttpURLConnection.HTTP_MOVED_TEMP;
import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
import static java.net.HttpURLConnection.HTTP_NO_CONTENT;
import static java.net.HttpURLConnection.HTTP_OK;
+import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
import static java.time.Duration.ofSeconds;
import static org.eclipse.che.api.factory.server.azure.devops.AzureDevOps.formatAuthorizationHeader;
import static org.eclipse.che.commons.lang.StringUtils.trimEnd;
@@ -40,6 +43,7 @@
import org.eclipse.che.api.factory.server.scm.exception.ScmBadRequestException;
import org.eclipse.che.api.factory.server.scm.exception.ScmCommunicationException;
import org.eclipse.che.api.factory.server.scm.exception.ScmItemNotFoundException;
+import org.eclipse.che.api.factory.server.scm.exception.ScmUnauthorizedException;
import org.eclipse.che.commons.lang.concurrent.LoggingUncaughtExceptionHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -80,7 +84,8 @@ public AzureDevOpsApiClient(
*
https://learn.microsoft.com/en-us/rest/api/azure/devops/graph/users/get?view=azure-devops-rest-7.0&tabs=HTTP
*/
public AzureDevOpsUser getUserWithOAuthToken(String token)
- throws ScmItemNotFoundException, ScmCommunicationException, ScmBadRequestException {
+ throws ScmItemNotFoundException, ScmCommunicationException, ScmBadRequestException,
+ ScmUnauthorizedException {
final String url =
String.format(
"%s/_apis/profile/profiles/me?api-version=%s",
@@ -94,7 +99,8 @@ public AzureDevOpsUser getUserWithOAuthToken(String token)
* organization.
*/
public AzureDevOpsUser getUserWithPAT(String pat, String organization)
- throws ScmItemNotFoundException, ScmCommunicationException, ScmBadRequestException {
+ throws ScmItemNotFoundException, ScmCommunicationException, ScmBadRequestException,
+ ScmUnauthorizedException {
final String url =
String.format(
"%s/%s/_apis/profile/profiles/me?api-version=%s",
@@ -103,7 +109,8 @@ public AzureDevOpsUser getUserWithPAT(String pat, String organization)
}
private AzureDevOpsUser getUser(String url, String authorizationHeader)
- throws ScmItemNotFoundException, ScmCommunicationException, ScmBadRequestException {
+ throws ScmItemNotFoundException, ScmCommunicationException, ScmBadRequestException,
+ ScmUnauthorizedException {
final HttpRequest userDataRequest =
HttpRequest.newBuilder(URI.create(url))
.headers("Authorization", authorizationHeader)
@@ -129,7 +136,8 @@ private T executeRequest(
HttpClient httpClient,
HttpRequest request,
Function, T> responseConverter)
- throws ScmBadRequestException, ScmItemNotFoundException, ScmCommunicationException {
+ throws ScmBadRequestException, ScmItemNotFoundException, ScmCommunicationException,
+ ScmUnauthorizedException {
try {
HttpResponse response =
httpClient.send(request, HttpResponse.BodyHandlers.ofInputStream());
@@ -145,6 +153,10 @@ private T executeRequest(
throw new ScmBadRequestException(body);
case HTTP_NOT_FOUND:
throw new ScmItemNotFoundException(body);
+ case HTTP_UNAUTHORIZED:
+ case HTTP_FORBIDDEN:
+ case HTTP_MOVED_TEMP:
+ throw new ScmUnauthorizedException(body, "azure-devops", "v2", "");
default:
throw new ScmCommunicationException(
"Unexpected status code " + response.statusCode() + " " + response,
diff --git a/wsmaster/che-core-api-factory-azure-devops/src/main/java/org/eclipse/che/api/factory/server/azure/devops/AzureDevOpsPersonalAccessTokenFetcher.java b/wsmaster/che-core-api-factory-azure-devops/src/main/java/org/eclipse/che/api/factory/server/azure/devops/AzureDevOpsPersonalAccessTokenFetcher.java
index 2c671c33ac..c6b3e274cc 100644
--- a/wsmaster/che-core-api-factory-azure-devops/src/main/java/org/eclipse/che/api/factory/server/azure/devops/AzureDevOpsPersonalAccessTokenFetcher.java
+++ b/wsmaster/che-core-api-factory-azure-devops/src/main/java/org/eclipse/che/api/factory/server/azure/devops/AzureDevOpsPersonalAccessTokenFetcher.java
@@ -163,7 +163,10 @@ public Optional isValid(PersonalAccessToken personalAccessToken) {
personalAccessToken.getToken(), personalAccessToken.getScmOrganization());
}
return Optional.of(personalAccessToken.getScmUserName().equals(user.getEmailAddress()));
- } catch (ScmItemNotFoundException | ScmCommunicationException | ScmBadRequestException e) {
+ } catch (ScmItemNotFoundException
+ | ScmCommunicationException
+ | ScmBadRequestException
+ | ScmUnauthorizedException e) {
return Optional.of(Boolean.FALSE);
}
}
@@ -184,7 +187,7 @@ public Optional> isValid(PersonalAccessTokenParams params)
user = azureDevOpsApiClient.getUserWithPAT(params.getToken(), params.getOrganization());
}
return Optional.of(Pair.of(Boolean.TRUE, user.getEmailAddress()));
- } catch (ScmItemNotFoundException | ScmBadRequestException e) {
+ } catch (ScmItemNotFoundException | ScmBadRequestException | ScmUnauthorizedException e) {
return Optional.empty();
}
}
diff --git a/wsmaster/che-core-api-factory-azure-devops/src/main/java/org/eclipse/che/api/factory/server/azure/devops/AzureDevOpsUserDataFetcher.java b/wsmaster/che-core-api-factory-azure-devops/src/main/java/org/eclipse/che/api/factory/server/azure/devops/AzureDevOpsUserDataFetcher.java
index b594687eed..482fb8158e 100644
--- a/wsmaster/che-core-api-factory-azure-devops/src/main/java/org/eclipse/che/api/factory/server/azure/devops/AzureDevOpsUserDataFetcher.java
+++ b/wsmaster/che-core-api-factory-azure-devops/src/main/java/org/eclipse/che/api/factory/server/azure/devops/AzureDevOpsUserDataFetcher.java
@@ -22,6 +22,7 @@
import org.eclipse.che.api.factory.server.scm.exception.ScmBadRequestException;
import org.eclipse.che.api.factory.server.scm.exception.ScmCommunicationException;
import org.eclipse.che.api.factory.server.scm.exception.ScmItemNotFoundException;
+import org.eclipse.che.api.factory.server.scm.exception.ScmUnauthorizedException;
/**
* Azure DevOps user data fetcher.
@@ -48,7 +49,8 @@ public AzureDevOpsUserDataFetcher(
@Override
protected GitUserData fetchGitUserDataWithOAuthToken(String token)
- throws ScmItemNotFoundException, ScmCommunicationException, ScmBadRequestException {
+ throws ScmItemNotFoundException, ScmCommunicationException, ScmBadRequestException,
+ ScmUnauthorizedException {
AzureDevOpsUser user = azureDevOpsApiClient.getUserWithOAuthToken(token);
return new GitUserData(user.getDisplayName(), user.getEmailAddress());
}
@@ -56,7 +58,8 @@ protected GitUserData fetchGitUserDataWithOAuthToken(String token)
@Override
protected GitUserData fetchGitUserDataWithPersonalAccessToken(
PersonalAccessToken personalAccessToken)
- throws ScmItemNotFoundException, ScmCommunicationException, ScmBadRequestException {
+ throws ScmItemNotFoundException, ScmCommunicationException, ScmBadRequestException,
+ ScmUnauthorizedException {
AzureDevOpsUser user =
azureDevOpsApiClient.getUserWithPAT(
personalAccessToken.getToken(), personalAccessToken.getScmOrganization());
diff --git a/wsmaster/che-core-api-factory-azure-devops/src/test/java/org/eclipse/che/api/factory/server/azure/devops/AzureDevOpsPersonalAccessTokenFetcherTest.java b/wsmaster/che-core-api-factory-azure-devops/src/test/java/org/eclipse/che/api/factory/server/azure/devops/AzureDevOpsPersonalAccessTokenFetcherTest.java
index ed51fe091f..62ff7aa037 100644
--- a/wsmaster/che-core-api-factory-azure-devops/src/test/java/org/eclipse/che/api/factory/server/azure/devops/AzureDevOpsPersonalAccessTokenFetcherTest.java
+++ b/wsmaster/che-core-api-factory-azure-devops/src/test/java/org/eclipse/che/api/factory/server/azure/devops/AzureDevOpsPersonalAccessTokenFetcherTest.java
@@ -18,6 +18,7 @@
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
import static java.net.HttpURLConnection.HTTP_FORBIDDEN;
+import static java.net.HttpURLConnection.HTTP_MOVED_TEMP;
import static org.eclipse.che.dto.server.DtoFactory.newDto;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
@@ -115,9 +116,23 @@ public void shouldThrowUnauthorizedExceptionIfTokenIsNotValid() throws Exception
when(oAuthAPI.getOrRefreshToken(anyString())).thenReturn(oAuthToken);
stubFor(
get(urlEqualTo("/_apis/profile/profiles/me?api-version=7.0"))
- .withHeader(HttpHeaders.AUTHORIZATION, equalTo("token " + azureOauthToken))
+ .withHeader(HttpHeaders.AUTHORIZATION, equalTo("Bearer " + azureOauthToken))
.willReturn(aResponse().withStatus(HTTP_FORBIDDEN)));
personalAccessTokenFetcher.fetchPersonalAccessToken(subject, wireMockServer.url("/"));
}
+
+ @Test(
+ expectedExceptions = ScmUnauthorizedException.class)
+ public void shouldThrowUnauthorizedExceptionOnRedirectResponse() throws Exception {
+ Subject subject = new SubjectImpl("Username", "id1", "token", false);
+ OAuthToken oAuthToken = newDto(OAuthToken.class).withToken(azureOauthToken).withScope("");
+ when(oAuthAPI.getOrRefreshToken(anyString())).thenReturn(oAuthToken);
+ stubFor(
+ get(urlEqualTo("/_apis/profile/profiles/me?api-version=7.0"))
+ .withHeader(HttpHeaders.AUTHORIZATION, equalTo("Bearer " + azureOauthToken))
+ .willReturn(aResponse().withStatus(HTTP_MOVED_TEMP)));
+
+ personalAccessTokenFetcher.fetchPersonalAccessToken(subject, wireMockServer.url("/"));
+ }
}