This is an automated email from the ASF dual-hosted git repository.

imbajin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hugegraph-toolchain.git

commit dbd72fa0b5ff92d83133613dfd776d1d70147bed
Author: dark <[email protected]>
AuthorDate: Sat Aug 29 23:11:31 2026 +0800

    fix(hubble): limit legacy password retention
    
    - retain credentials only for the 1.7 Basic fallback
    - avoid plaintext passwords in modern token sessions
    - cover modern and legacy login behavior
---
 .../hugegraph/controller/auth/LoginController.java | 18 ++++++++++---
 .../apache/hugegraph/unit/AuthSecurityTest.java    | 30 +++++++++++++++++++++-
 2 files changed, 43 insertions(+), 5 deletions(-)

diff --git 
a/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/controller/auth/LoginController.java
 
b/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/controller/auth/LoginController.java
index 955909cf4..3cdcf81be 100644
--- 
a/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/controller/auth/LoginController.java
+++ 
b/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/controller/auth/LoginController.java
@@ -87,13 +87,21 @@ public class LoginController extends BaseController {
         try {
             LoginResult result = this.authenticate(login, pdEnabled, address);
             Object user;
+            boolean requiresBasicGremlinAuth;
             if (!pdEnabled) {
                 user = currentUser(login.name());
+                try (HugeClient client =
+                             this.createLoginTokenClient(result.token())) {
+                    requiresBasicGremlinAuth =
+                            client.requiresBasicGremlinAuth();
+                }
             } else {
                 try (HugeClient client =
                              this.createLoginTokenClient(result.token())) {
                     client.assignGraph(PDHugeClientFactory.DEFAULT_GRAPHSPACE,
                                        null);
+                    requiresBasicGremlinAuth =
+                            client.requiresBasicGremlinAuth();
                     UserEntity entity = this.userService.getpersonal(
                             client, login.name());
                     user = entity;
@@ -107,10 +115,12 @@ public class LoginController extends BaseController {
             // HugeGraph 1.7's Gremlin HTTP channel only accepts Basic auth.
             // Keep the credential server-side for the session lifetime so
             // graph queries can use the same identity as REST requests.
-            this.setSession(Constant.PASSWORD_KEY, login.password());
-            this.setSession(Constant.PASSWORD_EXPIRE_AT_KEY,
-                            System.currentTimeMillis() +
-                            TOKEN_EXPIRE_SECONDS * 1000L);
+            if (requiresBasicGremlinAuth) {
+                this.setSession(Constant.PASSWORD_KEY, login.password());
+                this.setSession(Constant.PASSWORD_EXPIRE_AT_KEY,
+                                System.currentTimeMillis() +
+                                TOKEN_EXPIRE_SECONDS * 1000L);
+            }
             return user;
         } catch (Throwable e) {
             this.clearAuthSession();
diff --git 
a/hugegraph-hubble/hubble-be/src/test/java/org/apache/hugegraph/unit/AuthSecurityTest.java
 
b/hugegraph-hubble/hubble-be/src/test/java/org/apache/hugegraph/unit/AuthSecurityTest.java
index 86b837b5e..cd3d8f759 100644
--- 
a/hugegraph-hubble/hubble-be/src/test/java/org/apache/hugegraph/unit/AuthSecurityTest.java
+++ 
b/hugegraph-hubble/hubble-be/src/test/java/org/apache/hugegraph/unit/AuthSecurityTest.java
@@ -825,6 +825,7 @@ public class AuthSecurityTest {
         RequestContextHolder.setRequestAttributes(
                 new ServletRequestAttributes(request));
         TestLoginController controller = new TestLoginController();
+        controller.basicGremlinAuth = true;
         HugeConfig config = Mockito.mock(HugeConfig.class);
         Mockito.when(config.get(HubbleOptions.PD_ENABLED)).thenReturn(false);
         setField(controller, "config", config);
@@ -846,6 +847,29 @@ public class AuthSecurityTest {
                           System.currentTimeMillis());
     }
 
+    @Test
+    public void testModernLoginDoesNotRetainPassword() throws Exception {
+        MockHttpServletRequest request = new MockHttpServletRequest();
+        RequestContextHolder.setRequestAttributes(
+                new ServletRequestAttributes(request));
+        TestLoginController controller = new TestLoginController();
+        HugeConfig config = Mockito.mock(HugeConfig.class);
+        Mockito.when(config.get(HubbleOptions.PD_ENABLED)).thenReturn(false);
+        setField(controller, "config", config);
+        Login login = new Login();
+        login.name("admin");
+        login.password("pa");
+
+        controller.login(login);
+
+        Assert.assertEquals("server-token", request.getSession().getAttribute(
+                            Constant.TOKEN_KEY));
+        Assert.assertNull(request.getSession().getAttribute(
+                          Constant.PASSWORD_KEY));
+        Assert.assertNull(request.getSession().getAttribute(
+                          Constant.PASSWORD_EXPIRE_AT_KEY));
+    }
+
     @Test
     public void testAuthContextUsesCurrentSessionIdentity() throws Exception {
         MockHttpServletRequest request = new MockHttpServletRequest();
@@ -1033,6 +1057,7 @@ public class AuthSecurityTest {
         private HugeClient userClient;
         private String validationToken;
         private LoginAttemptGuard attemptGuard;
+        private boolean basicGremlinAuth;
 
         private TestLoginController() {
             this.attemptGuard = Mockito.mock(LoginAttemptGuard.class);
@@ -1080,7 +1105,10 @@ public class AuthSecurityTest {
         @Override
         protected HugeClient createLoginTokenClient(String token) {
             if (this.userClient == null) {
-                return super.createLoginTokenClient(token);
+                HugeClient client = Mockito.mock(HugeClient.class);
+                Mockito.when(client.requiresBasicGremlinAuth())
+                       .thenReturn(this.basicGremlinAuth);
+                return client;
             }
             this.validationToken = token;
             return this.userClient;

Reply via email to