diff --git a/wsmaster/che-core-api-auth-gitlab/pom.xml b/wsmaster/che-core-api-auth-gitlab/pom.xml
index bc306f4c5b6..77802fddade 100644
--- a/wsmaster/che-core-api-auth-gitlab/pom.xml
+++ b/wsmaster/che-core-api-auth-gitlab/pom.xml
@@ -35,6 +35,10 @@
com.google.inject
guice
+
+ com.google.oauth-client
+ google-oauth-client
+
jakarta.inject
jakarta.inject-api
diff --git a/wsmaster/che-core-api-auth-gitlab/src/main/java/org/eclipse/che/security/oauth/GitLabOAuthAuthenticator.java b/wsmaster/che-core-api-auth-gitlab/src/main/java/org/eclipse/che/security/oauth/GitLabOAuthAuthenticator.java
index ded56bebfd2..ebba4a2021c 100644
--- a/wsmaster/che-core-api-auth-gitlab/src/main/java/org/eclipse/che/security/oauth/GitLabOAuthAuthenticator.java
+++ b/wsmaster/che-core-api-auth-gitlab/src/main/java/org/eclipse/che/security/oauth/GitLabOAuthAuthenticator.java
@@ -91,11 +91,11 @@ protected O getJson(String getUserUrl, String accessToken, Class userClas
public OAuthToken getToken(String userId) throws IOException {
final OAuthToken token = super.getToken(userId);
try {
- if (token == null
- || token.getToken() == null
- || token.getToken().isEmpty()
- || isNullOrEmpty(
- getJson(gitlabUserEndpoint, token.getToken(), GitLabUser.class).getId())) {
+ if (token == null || token.getToken() == null || token.getToken().isEmpty()) {
+ return null;
+ }
+ GitLabUser user = getJson(gitlabUserEndpoint, token.getToken(), GitLabUser.class);
+ if (user == null || isNullOrEmpty(user.getId())) {
return null;
}
} catch (OAuthAuthenticationException e) {
diff --git a/wsmaster/che-core-api-auth-gitlab/src/test/java/org/eclipse/che/security/oauth/GitLabAuthenticatorTest.java b/wsmaster/che-core-api-auth-gitlab/src/test/java/org/eclipse/che/security/oauth/GitLabAuthenticatorTest.java
new file mode 100644
index 00000000000..cae662aeae8
--- /dev/null
+++ b/wsmaster/che-core-api-auth-gitlab/src/test/java/org/eclipse/che/security/oauth/GitLabAuthenticatorTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2012-2024 Red Hat, Inc.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.security.oauth;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.github.tomakehurst.wiremock.client.WireMock;
+import com.github.tomakehurst.wiremock.common.Slf4jNotifier;
+import com.google.api.client.auth.oauth2.StoredCredential;
+import com.google.api.client.util.store.MemoryDataStoreFactory;
+import com.google.common.net.HttpHeaders;
+import java.lang.reflect.Field;
+import org.eclipse.che.api.auth.shared.dto.OAuthToken;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class GitLabAuthenticatorTest {
+ WireMockServer wireMockServer;
+ WireMock wireMock;
+
+ @BeforeClass
+ public void setup() {
+ wireMockServer =
+ new WireMockServer(wireMockConfig().notifier(new Slf4jNotifier(false)).dynamicPort());
+ wireMockServer.start();
+ WireMock.configureFor("localhost", wireMockServer.port());
+ wireMock = new WireMock("localhost", wireMockServer.port());
+ }
+
+ @Test
+ public void shouldGetToken() throws Exception {
+ // given
+ GitLabOAuthAuthenticator gitLabOAuthAuthenticator =
+ new GitLabOAuthAuthenticator(
+ "id", "secret", wireMockServer.url("/"), "https://che.api.com");
+ Field flowField = OAuthAuthenticator.class.getDeclaredField("flow");
+ Field credentialDataStoreField =
+ ((Class) flowField.getGenericType()).getDeclaredField("credentialDataStore");
+ credentialDataStoreField.setAccessible(true);
+ credentialDataStoreField.set(
+ flowField.get(gitLabOAuthAuthenticator),
+ new MemoryDataStoreFactory()
+ .getDataStore("test")
+ .set("userId", new StoredCredential().setAccessToken("token")));
+ stubFor(
+ get(urlEqualTo("/api/v4/user"))
+ .withHeader(HttpHeaders.AUTHORIZATION, equalTo("Bearer token"))
+ .willReturn(aResponse().withBody("{\"id\": \"testId\"}")));
+ // when
+ OAuthToken token = gitLabOAuthAuthenticator.getToken("userId");
+ // then
+ assertEquals(token.getToken(), "token");
+ }
+
+ @Test
+ public void shouldGetEmptyToken() throws Exception {
+ // given
+ GitLabOAuthAuthenticator gitLabOAuthAuthenticator =
+ new GitLabOAuthAuthenticator(
+ "id", "secret", wireMockServer.url("/"), "https://che.api.com");
+ Field flowField = OAuthAuthenticator.class.getDeclaredField("flow");
+ Field credentialDataStoreField =
+ ((Class) flowField.getGenericType()).getDeclaredField("credentialDataStore");
+ credentialDataStoreField.setAccessible(true);
+ credentialDataStoreField.set(
+ flowField.get(gitLabOAuthAuthenticator),
+ new MemoryDataStoreFactory()
+ .getDataStore("test")
+ .set("userId", new StoredCredential().setAccessToken("token")));
+ stubFor(
+ get(urlEqualTo("/api/v4/user"))
+ .withHeader(HttpHeaders.AUTHORIZATION, equalTo("Bearer token"))
+ .willReturn(aResponse().withBody("{}")));
+ // when
+ OAuthToken token = gitLabOAuthAuthenticator.getToken("userId");
+ // then
+ assertNull(token);
+ }
+}
diff --git a/wsmaster/che-core-api-auth/src/main/java/org/eclipse/che/security/oauth/OAuthAuthenticator.java b/wsmaster/che-core-api-auth/src/main/java/org/eclipse/che/security/oauth/OAuthAuthenticator.java
index 023da7f91b3..7206188cb64 100644
--- a/wsmaster/che-core-api-auth/src/main/java/org/eclipse/che/security/oauth/OAuthAuthenticator.java
+++ b/wsmaster/che-core-api-auth/src/main/java/org/eclipse/che/security/oauth/OAuthAuthenticator.java
@@ -285,7 +285,8 @@ protected O getJson(String getUserUrl, String accessToken, Class userClas
* none token found for user then {@code null} will be returned, when user have expired token
* and it can't be refreshed then {@code null} will be returned
* @throws IOException when error occurs during token loading
- * @see OAuthTokenProvider#getToken(String, String)
+ * @see OAuthTokenProvider#getToken(String, String) TODO: return Optional to avoid
+ * returning null.
*/
public OAuthToken getToken(String userId) throws IOException {
if (!isConfigured()) {